1
0
mirror of https://github.com/imapsync/imapsync.git synced 2024-11-17 00:02:29 +01:00
This commit is contained in:
Nick Bebout 2018-05-07 09:04:23 -05:00
parent 65f8552a91
commit 9a927be251
292 changed files with 53540 additions and 39537 deletions

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: CREDITS,v 1.190 2017/01/25 23:58:21 gilles Exp gilles $ # $Id: CREDITS,v 1.191 2018/04/08 17:27:58 gilles Exp gilles $
If you want to make a donation to me, imapsync author, Gilles LAMIRAL, If you want to make a donation to me, imapsync author, Gilles LAMIRAL,
use any of the following ways: use any of the following ways:
@ -8,12 +8,12 @@ b) If you can read french, please use the following wishlist :
http://amazon.fr/gp/registry/wishlist/37RZF7PPCD7YL http://amazon.fr/gp/registry/wishlist/37RZF7PPCD7YL
(books will be send with free postal cost) (books will be send with free postal cost)
c) my paypal account is gilles.lamiral@laposte.net c) my paypal account is gilles@lamiral.info
http://imapsync.lamiral.info/S/paypal.shtml http://imapsync.lamiral.info/S/paypal.shtml
My postal address is: My postal address is:
Gilles LAMIRAL Gilles LAMIRAL
La Billais 22 La Billais
35580 Baulon 35580 Baulon
FRANCE FRANCE

228
ChangeLog
View File

@ -1,17 +1,237 @@
RCS file: RCS/imapsync,v RCS file: RCS/imapsync,v
Working file: imapsync Working file: imapsync
head: 1.836 head: 1.882
branch: branch:
locks: strict locks: strict
gilles: 1.836 gilles: 1.882
access list: access list:
symbolic names: symbolic names:
keyword substitution: kv keyword substitution: kv
total revisions: 836; selected revisions: 836 total revisions: 882; selected revisions: 882
description: description:
---------------------------- ----------------------------
revision 1.836 locked by: gilles; revision 1.882 locked by: gilles;
date: 2018/05/05 21:10:43; author: gilles; state: Exp; lines: +8 -8
typo
----------------------------
revision 1.881
date: 2018/05/05 20:43:36; author: gilles; state: Exp; lines: +96 -61
proofread the doc part. ispell on README.
----------------------------
revision 1.880
date: 2018/05/05 12:44:21; author: gilles; state: Exp; lines: +26 -21
Splitted sub usage() with call to sub mypod2usage(). Crit level 4 on open/close not far away.
----------------------------
revision 1.879
date: 2018/04/20 13:02:13; author: gilles; state: Exp; lines: +20 -13
Back to `` because of backtick() does not work always on Darwin
----------------------------
revision 1.878
date: 2018/04/19 00:51:45; author: gilles; state: Exp; lines: +76 -40
Perlcrit. Removed the select in teelaunch()
Perlcrit. *STDERR change is now localized.
Perlcrit. Hard 'LOG_imapsync' is now $DEFAULT_LOGDIR
Proxy mode. Log file will be named with a suffix "_remote.txt"
Refactor. sub logfile() is deglobalized. (removed $debug lines)
----------------------------
revision 1.877
date: 2018/04/18 22:00:46; author: gilles; state: Exp; lines: +31 -13
Changed sub myprint and sub myprintf in order to suppress the select in teelaunch
----------------------------
revision 1.876
date: 2018/04/18 03:02:32; author: gilles; state: Exp; lines: +20 -17
Bugfix. ARRAY ref not defined with --subscribed
----------------------------
revision 1.875
date: 2018/04/18 02:27:18; author: gilles; state: Exp; lines: +32 -25
Refactor. $tmpdir unglobalized
Win32. No USR1 on Windows so skip signals tests on Win32
----------------------------
revision 1.874
date: 2018/04/18 00:46:46; author: gilles; state: Exp; lines: +53 -40
Perlcrit. Use IPC::Open3::open3 instead of backticks ``
----------------------------
revision 1.873
date: 2018/04/17 00:24:54; author: gilles; state: Exp; lines: +9 -9
Added SERVER_SOFTWARE
Added SERVER_PORT
----------------------------
revision 1.872
date: 2018/04/16 23:10:03; author: gilles; state: Exp; lines: +17 -11
Bugfix to pass --tests under root user.
----------------------------
revision 1.871
date: 2018/04/13 18:00:06; author: gilles; state: Exp; lines: +71 -12
Added toggle sleep from 2s to 0s with signal USR1
----------------------------
revision 1.870
date: 2018/04/08 17:25:54; author: gilles; state: Exp; lines: +46 -46
Changed gilles.lamiral@laposte.net => gilles@lamiral.info
----------------------------
revision 1.869
date: 2018/04/08 17:21:15; author: gilles; state: Exp; lines: +29 -30
https://imapsync.lamiral.info/ instead of http://imapsync.lamiral.info/ in ID support-url
Removed uname info from banner, adder ram info.
Change utf8 char ° to nb in tests summary
----------------------------
revision 1.868
date: 2018/04/03 01:55:24; author: gilles; state: Exp; lines: +13 -12
Renamed total_ram_memory() => ram_memory_info()
----------------------------
revision 1.867
date: 2018/04/03 00:35:58; author: gilles; state: Exp; lines: +21 -18
Refactor. sub under_cgi_context() uses $mysync.
----------------------------
revision 1.866
date: 2018/03/29 04:58:11; author: gilles; state: Exp; lines: +10 -9
Changed inline signal message
----------------------------
revision 1.865
date: 2018/03/29 04:50:26; author: gilles; state: Exp; lines: +98 -86
Moved the inline help "I am asked to stop immediately" after the final stats.
Tidied up sub myGetOptions()
----------------------------
revision 1.864
date: 2018/03/28 21:33:28; author: gilles; state: Exp; lines: +12 -18
Before tidy up sub myGetOptions
----------------------------
revision 1.863
date: 2018/03/28 16:57:22; author: gilles; state: Exp; lines: +10 -8
Added inline advice to resync after an end commanded by a TERM or QUIT signal.
----------------------------
revision 1.862
date: 2018/03/28 14:48:37; author: gilles; state: Exp; lines: +21 -20
Reduced the loadavg ingo in the header status in CGI context.
Added the hostname in in the header status in CGI context.
----------------------------
revision 1.861
date: 2018/03/27 03:04:03; author: gilles; state: Exp; lines: +41 -48
Refactor. Use of debugmemory()
Moved the hostname printing at first line. The goal is for clarity when in proxy mode.
Added free RAM info in the banner
Added free RAM and total RAM in the status in CGI context.
----------------------------
revision 1.860
date: 2018/03/26 21:14:01; author: gilles; state: Exp; lines: +97 -67
Reviewed tests_get_options_cgi(), renamed to tests_get_options_cgi_context()
Reviewed tests_get_options
----------------------------
revision 1.859
date: 2018/03/22 12:55:34; author: gilles; state: Exp; lines: +13 -8
Bugfix. Predeclare $sync->{folder} as ARRAY ref. $sync->{folder} = [] ;
----------------------------
revision 1.858
date: 2018/03/21 07:53:26; author: gilles; state: Exp; lines: +14 -11
Refactoring. Deglobalized $justconnect
----------------------------
revision 1.857
date: 2018/03/21 07:40:12; author: gilles; state: Exp; lines: +80 -31
Refactor. Changed how --f1f2 is handled. Was a hash, now a list.
----------------------------
revision 1.856
date: 2018/03/20 02:24:52; author: gilles; state: Exp; lines: +31 -19
Refactoring. Deglobalized @folder
----------------------------
revision 1.855
date: 2018/03/19 14:15:53; author: gilles; state: Exp; lines: +18 -21
Refactoring. Deglobalized $addheader
Refactoring. Deglobalized $justlogin
----------------------------
revision 1.854
date: 2018/03/19 13:45:31; author: gilles; state: Exp; lines: +32 -25
Unglobalized $version
Unglobalized $releasecheck
Added sub debugmemory()
----------------------------
revision 1.853
date: 2018/03/12 13:43:11; author: gilles; state: Exp; lines: +9 -9
Back to default signals. INT => reconnect. TERM or QUIT => stats and exit. (cgicontext ignored TERM)
----------------------------
revision 1.852
date: 2018/03/12 03:11:04; author: gilles; state: Exp; lines: +132 -29
Added --sigexit; For example --sigexit QUIT --sigexit TERM to exit when receiving QUIT or TERM signals.
Added --sigreconnect. For example --sigreconnect INT to reconnect to both imap servers when receiving INT signal.
Added --sigignore. For example --sigignore TERM to "ignore" the TERM signal. In fact print stats during the sync.
Default is like: --sigexit QUIT --sigexit TERM --sigreconnect INT
Added sub sig_install() to install any behavior with any signal (the ones actually received in Unix).
Number of tests with --tests is 1137
----------------------------
revision 1.851
date: 2018/03/04 15:19:04; author: gilles; state: Exp; lines: +10 -10
Inline help. Clarified --errorsmax inline help.
----------------------------
revision 1.850
date: 2018/02/21 04:15:32; author: gilles; state: Exp; lines: +66 -41
Option --abort now creates a log too, in order to see if imapsync ends by signal come from --abort or something else.
----------------------------
revision 1.849
date: 2018/02/18 18:45:36; author: gilles; state: Exp; lines: +14 -10
Added \t\r\n characters replaced by _ in sub filter_forbidden_characters()
----------------------------
revision 1.848
date: 2018/02/07 00:58:59; author: gilles; state: Exp; lines: +50 -28
Cleaned up --releasecheck stuff.
Clarified SSL_VERIFY_NONE default.
----------------------------
revision 1.847
date: 2017/12/18 11:04:26; author: gilles; state: Exp; lines: +56 -33
Bugfix. Fixed sub epoch() to allow that kind of silly INTERNALDATE 00-Jan-0000 00:00:00 +0000
(Thanks to IBM Domino...)
Added inline documentation about --releasecheck and --noreleasecheck
Default upstream is still --releasecheck. Just a line to change to have --noreleasecheck by default (as before)
Bugfix. --releasecheck on was hardcoded in cgi context. Now it depends on the default behavior chosen.
Bug pending. Still have to fix --releasecheck on with --help
----------------------------
revision 1.846
date: 2017/11/30 02:00:12; author: gilles; state: Exp; lines: +34 -12
Added sub memory_stress
Added sub tests_memory_stress
memory_stress() crunch 3/4 of the RAM.
tests_memory_stress() is the associated test.
----------------------------
revision 1.845
date: 2017/11/28 23:36:43; author: gilles; state: Exp; lines: +51 -29
Added --noresyncflags : Do not resync flags for already transfered messages.
May be useful when a user has already started to play with its host2 account.
----------------------------
revision 1.844
date: 2017/11/16 14:38:38; author: gilles; state: Exp; lines: +107 -43
Crit. Removed 4 "Warnings disabled". crit level 4
----------------------------
revision 1.843
date: 2017/11/05 22:23:57; author: gilles; state: Exp; lines: +38 -30
Added --nocheckfoldersexist ( Default is like --checkfoldersexist )
----------------------------
revision 1.842
date: 2017/10/30 18:47:37; author: gilles; state: Exp; lines: +246 -115
Refactoring. Removed global variables $h1_prefix and $h2_prefix
Bugfix. cpu_number() returns always an integer >= 1.
----------------------------
revision 1.841
date: 2017/10/27 12:37:39; author: gilles; state: Exp; lines: +55 -41
Detect extra arguments. Meaning usually a quoting issue in the command line, options not well parsed.
----------------------------
revision 1.840
date: 2017/10/22 14:28:00; author: gilles; state: Exp; lines: +9 -9
No limitssssss
----------------------------
revision 1.839
date: 2017/10/04 17:50:29; author: gilles; state: Exp; lines: +132 -39
In case the pidfile already exists, remove it if no process match its content.
Do nothing if the pidfile doesn't content a pid number 0<pid<65536
----------------------------
revision 1.838
date: 2017/09/22 08:12:49; author: gilles; state: Exp; lines: +28 -12
Added Polska to possible_special (not for all).
Started sub tests_write_pidfile()
----------------------------
revision 1.837
date: 2017/09/20 20:14:14; author: gilles; state: Exp; lines: +42 -19
Usability. More verbose with ssl probing.
----------------------------
revision 1.836
date: 2017/09/05 16:14:53; author: gilles; state: Exp; lines: +189 -182 date: 2017/09/05 16:14:53; author: gilles; state: Exp; lines: +189 -182
Reread the README part. Changed order, rewrote some parts, added options. Reread the README part. Changed order, rewrote some parts, added options.
---------------------------- ----------------------------

View File

@ -1,12 +1,27 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Archiving.txt,v 1.6 2017/07/13 14:44:07 gilles Exp gilles $ $Id: FAQ.Archiving.txt,v 1.7 2018/04/24 00:16:21 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
============================================ ============================================
Imapsync tips about archiving messages. Imapsync issues and tips about archiving.
============================================ ============================================
Questions answered in this FAQ are:
Q. Can I archive different accounts on the same destination account,
each account on a separate folder?
Q. How to move emails from one IMAP folder to another either on the
same IMAP server or a different one?
For example, all messages older than 1 year, move from INBOX to Archive.
Q. Can imapsync be used to maintain a local offline copy of a
mailbox from host1, eg for backup purposes, so that if the
server fails, then the mailbox could be reinstated,
ideally without requiring a second IMAP host?
======================================================================= =======================================================================
Q. Can I archive different accounts on the same destination account, Q. Can I archive different accounts on the same destination account,
each account on a separate folder? each account on a separate folder?
@ -18,7 +33,6 @@ R. Yes. Use --subfolder2
It is done it by adding two --regextrans2 options before It is done it by adding two --regextrans2 options before
all others. Add --debug to see what's really going on. all others. Add --debug to see what's really going on.
Example: Example:
imapsync ... --user1 foo --subfolder2 foo imapsync ... --user1 foo --subfolder2 foo
@ -46,4 +60,25 @@ Add option --delete if you want to move messages, instead of just copy/sync them
R2. See also file FAQ.Folders_Mapping.txt R2. See also file FAQ.Folders_Mapping.txt
======================================================================= =======================================================================
Q. Can imapsync be used to maintain a local offline copy of a
mailbox from host1, eg for backup purposes, so that if the
server fails, then the mailbox could be reinstated,
ideally without requiring a second IMAP host?
R1. No. Imapsync plays with imap servers only.
R2. Imapsync can't but rick-sanders-imap-tools can!
See https://github.com/andrewnimmo/rick-sanders-imap-tools
Back up and restore IMAP accounts with imapdump.pl and dumptoIMAP.pl
======================================================================= =======================================================================
=======================================================================
=======================================================================

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Contacts_Calendars.txt,v 1.5 2017/01/06 14:11:13 gilles Exp gilles $ $Id: FAQ.Contacts_Calendars.txt,v 1.7 2018/03/07 04:26:04 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -7,12 +7,15 @@ This documentation is also at http://imapsync.lamiral.info/#doc
Imapsync issues about syncing Contacts & Calendars. Imapsync issues about syncing Contacts & Calendars.
========================================================= =========================================================
Questions anwswered in this FAQ are: Questions answered in this FAQ are:
Q. Can I copy or sync Calendar or Contacts with imapsync? Q. Can I copy or sync Calendar or Contacts with imapsync?
Q. How can I avoid copying Calendar or Contacts folders? Q. How can I avoid copying Calendar or Contacts folders?
Q. How can I copy or synchronize Calendars or Contacts? Q. How can I copy or synchronize Calendars or Contacts?
Now the questions again with their answers.
======================================================================= =======================================================================
Q. Can I copy or sync Calendar or Contacts with imapsync? Q. Can I copy or sync Calendar or Contacts with imapsync?

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Dates.txt,v 1.6 2017/08/29 05:34:55 gilles Exp gilles $ $Id: FAQ.Dates.txt,v 1.7 2018/03/07 04:12:37 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -7,7 +7,7 @@ This documentation is also at http://imapsync.lamiral.info/#doc
Imapsync tips about dates. Imapsync tips about dates.
=============================== ===============================
Questions anwswered in this FAQ are: Questions answered in this FAQ are:
Q. We have found that the time and date displayed have been changed to Q. We have found that the time and date displayed have been changed to
the time at which the file was synchronized. What happened? Any fix? the time at which the file was synchronized. What happened? Any fix?

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: FAQ.Domino.txt,v 1.8 2017/03/02 12:54:15 gilles Exp gilles $ # $Id: FAQ.Domino.txt,v 1.9 2018/03/13 03:22:55 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -11,6 +11,13 @@ This documentation is also at http://imapsync.lamiral.info/#doc
======================================================================= =======================================================================
Q. From Domino Notes to XXX Q. From Domino Notes to XXX
R1. Use --domino1, like this:
imapsync ... --domino1
R2. Or use the following options:
On Windows use: On Windows use:
imapsync.exe ... --sep1 "\\" --prefix1 "" --messageidnodomain imapsync.exe ... --sep1 "\\" --prefix1 "" --messageidnodomain
@ -22,6 +29,13 @@ On Unix use:
======================================================================= =======================================================================
Q. From XXX to Domino Notes Q. From XXX to Domino Notes
R1. Use --domino2, like this:
imapsync ... --domino2
R2. Or follow this:
Domino doesn't accept INBOX subfolders. Domino doesn't accept INBOX subfolders.
On Windows: On Windows:
@ -73,6 +87,5 @@ For Domino 853FP6 on Linux, we used this command on Unix:
--regexmess 's{\A(.*?(?! ^$))^Date:(.*?)$}{$1Migratedbyus:$2\nx-MailDate:$2}gxms' --regexmess 's{\A(.*?(?! ^$))^Date:(.*?)$}{$1Migratedbyus:$2\nx-MailDate:$2}gxms'
======================================================================= =======================================================================
======================================================================= =======================================================================

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Duplicates.txt,v 1.12 2017/08/31 03:06:45 gilles Exp gilles $ $Id: FAQ.Duplicates.txt,v 1.14 2018/05/02 12:21:54 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -8,7 +8,7 @@ This documentation is also at http://imapsync.lamiral.info/#doc
======================================================================= =======================================================================
======================================================================= =======================================================================
Q. How can I remove duplicates in an lone account? Q. How can I remove duplicates in a lone account?
R. Just run imapsync on the same account with option --delete2duplicates, R. Just run imapsync on the same account with option --delete2duplicates,
ie, with host1 == host2 and user1 == user2 ie, with host1 == host2 and user1 == user2
@ -43,15 +43,15 @@ So if it does generate duplicates it means a problem occurs
with message identification. It happens sometimes with IMAP with message identification. It happens sometimes with IMAP
servers changing the "Message-Id" header line or one or more servers changing the "Message-Id" header line or one or more
of the "Received:" header lines in the header part of messages. of the "Received:" header lines in the header part of messages.
Imapsync uses "Message-Id" header line and "Received:" header By default, Imapsync uses "Message-Id" header line and
lines to identify messages on both sides. "Received:" header lines to identify messages on both sides.
R1. R1.
A first solution is to use option --useuid. A first solution is to use option --useuid.
With option --useuid, imapsync doesn't use header lines With option --useuid, imapsync doesn't use header lines
to identify and compare messages in folders. to identify and compare messages in folders.
Instead of some headers, --useuid tell imapsync to use Instead of some headers, --useuid tell imapsync to use
the imap UIDs given by imap servers on bith sides. the imap UIDs given by imap servers on both sides.
To avoid duplicates on next runs, imapsync uses a local cache To avoid duplicates on next runs, imapsync uses a local cache
where it keeps UIDs already transfered. where it keeps UIDs already transfered.
@ -60,18 +60,19 @@ where it keeps UIDs already transfered.
There is an issue when --useuid is not used the first time. There is an issue when --useuid is not used the first time.
A big issue with --useuid is that it doesn't generate duplicates if A big issue with --useuid is that it doesn't generate duplicates if
used from the first time but it does generate duplicates after a previous used from the first time but it does generate duplicates after a previous
run without --useuid (because then uses a different method to identify run without --useuid (because it then uses a different method to identify
the messages). the messages).
A solution? Two solutions. A solution? Two solutions.
The easiest is --delete2 The easiest is --delete2 if you are permitted to use it.
if you are permitted to use it. Option --delete2 removes messages on host2 Option --delete2 removes messages on host2
that are not on host1 so with --delete2 you go for resyncing all that are not on host1. So, with --delete2 you go for resyncing all
messages again but all previously transferred messages are deleted, messages again but all previously transferred messages are deleted,
and also messages previously there without imapsync. but also messages previously there without imapsync.
So --useuid --delete2 is easy to remove duplicates but not for So --useuid --delete2 is easy to remove duplicates but not for
all context. all contexts. The host2 account must be considered as a strict
replication of the host1 account, ie, not active.
A second solution, better if R2 works (see R2 below), is to build A second solution, better if R2 works (see R2 below), is to build
the cache before using --useuid the cache before using --useuid
@ -120,8 +121,8 @@ can be deleted with option --delete2duplicates
imapsync ... --useheader "Message-Id" --delete2duplicates imapsync ... --useheader "Message-Id" --delete2duplicates
Another good way toward a solution is to isolate two or three messages Another good way toward a solution is to isolate two or three messages
in a BUG folder and send me the --debug output by email at in a BUG folder and send me the --debug output by email to
gilles.lamiral@laposte.net gilles@lamiral.info
imapsync ... --debug --folder BUG imapsync ... --debug --folder BUG
@ -133,10 +134,10 @@ Remark. (Trick found by Tomasz Kaczmarski)
Option --useheader "Message-Id" asks the server to send only header Option --useheader "Message-Id" asks the server to send only header
lines beginning with "Message-Id". Some (buggy) servers send the whole lines beginning with "Message-Id". Some (buggy) servers send the whole
header (all lines) instead of the "Message-Id" line. In that case, a header (all lines) instead of the "Message-Id" line. In that case, a
trick to keep the --useheader filtering behaviour is to use trick to keep the --useheader filtering behavior is to use
--skipheader with a negative lookahead pattern: --skipheader with a negative lookahead pattern:
imapsync ... --skipheader "^(?!Message-Id)" imapsync ... --skipheader "^(?!Message-Id)"
Read it as "skip every header except Message-Id". Read it as "skip every header except Message-Id".

View File

@ -1,5 +1,5 @@
$Id: FAQ.Exchange.txt,v 1.34 2017/07/18 21:27:18 gilles Exp gilles $ $Id: FAQ.Exchange.txt,v 1.38 2018/03/21 16:26:23 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -7,7 +7,7 @@ This documentation is also at http://imapsync.lamiral.info/#doc
Imapsync tips for Exchange 20xx and Office365. Specific issues and solutions. Imapsync tips for Exchange 20xx and Office365. Specific issues and solutions.
================================================================================= =================================================================================
Questions anwswered in this FAQ are: Questions answered in this FAQ are:
Q. Can I use imapsync to transfer from or to Exchange or Office365 accounts? Q. Can I use imapsync to transfer from or to Exchange or Office365 accounts?
@ -58,12 +58,18 @@ Q. How to sync from any to Exchange2007?
Q. How to sync from Microsoft Exchange 2000 IMAP4rev1 server? Q. How to sync from Microsoft Exchange 2000 IMAP4rev1 server?
Now the questions again with their answers.
======================================================================= =======================================================================
Q. Can I use imapsync to transfer from or to Exchange or Office365 accounts? Q. Can I use imapsync to transfer from or to Exchange or Office365 accounts?
R. Yes. But IMAP access to a Exchange or Office365 account is not always R. Yes. But IMAP access to a Exchange or Office365 account is not always
allowed by default so it has to be allowed in the server configuration allowed by default so it has to be allowed in the server configuration
part: part.
Exchange: https://technet.microsoft.com/en-us/library/bb124489(v=exchg.150).aspx
Office365: https://support.microsoft.com/en-us/help/2416434/how-to-enable-or-disable-pop3-imap-mapi-outlook-web-app-or-exchange-ac
======================================================================= =======================================================================
Q. How to sync from XXX to Exchange 2010/2013/2016 Q. How to sync from XXX to Exchange 2010/2013/2016
@ -71,11 +77,17 @@ Q. How to sync from XXX to Exchange 2010/2013/2016
R0. IMAP is not enable by default on Exchange, see how to enable it: R0. IMAP is not enable by default on Exchange, see how to enable it:
https://technet.microsoft.com/en-us/library/bb124489(v=exchg.150).aspx https://technet.microsoft.com/en-us/library/bb124489(v=exchg.150).aspx
R1. Following is a command line resume that solves most encountered R1. Following is a command line resume that solves most encountered
issues when migrating to Exchange. To fully understand or change issues when migrating to Exchange. To fully understand or change
the details you have to read the next Q/R sections. the details you have to read the next Q/R sections.
On Windows:
On Windows, use:
imapsync.exe ... --exchange2
or use (before imapsync release 1.836):
imapsync.exe ... ^ imapsync.exe ... ^
--maxsize 10000000 ^ --maxsize 10000000 ^
@ -84,7 +96,11 @@ On Windows:
--disarmreadreceipts ^ --disarmreadreceipts ^
--regexmess "s,(.{9900}),$1\r\n,g" --regexmess "s,(.{9900}),$1\r\n,g"
On Unix: On Unix, use:
imapsync ... --exchange2
or use (before imapsync release 1.836):
imapsync ... \ imapsync ... \
--maxsize 10000000 \ --maxsize 10000000 \
@ -102,14 +118,22 @@ instead of --maxlinelengthcmd 'reformime -r7'
======================================================================= =======================================================================
Q. How to sync from XXX to Office365 Q. How to sync from XXX to Office365
R0. IMAP is not enable by default on Office365, see how to enable it:
https://support.microsoft.com/en-us/help/2416434/how-to-enable-or-disable-pop3-imap-mapi-outlook-web-app-or-exchange-ac
https://technet.microsoft.com/en-us/library/gg298947(v=exchg.150).aspx
https://support.context.io/hc/en-us/articles/213586243-Enabling-IMAP-for-Office365
R. Here is a command line resume that solves most encountered issues when R. Here is a command line resume that solves most encountered issues when
migrating to Office365. It's similar with Exchange except for some migrating to Office365. It's similar with Exchange except for some
values. To understand or change the details you have to read values. To understand or change the details you have to read
next Q/R sections. next Q/R sections.
On Windows: On Windows, use:
imapsync.exe ... --office2
or use (before imapsync release 1.836):
imapsync.exe ... ^ imapsync.exe ... ^
--maxsize 45000000 ^ --maxsize 45000000 ^
--maxmessagespersecond 4 ^ --maxmessagespersecond 4 ^
@ -117,7 +141,11 @@ On Windows:
--disarmreadreceipts ^ --disarmreadreceipts ^
--regexmess "s,(.{10500}),$1\r\n,g" --regexmess "s,(.{10500}),$1\r\n,g"
On Unix: On Unix, use:
imapsync ... --office2
or use (before imapsync release 1.836):
imapsync ... \ imapsync ... \
--maxsize 45000000 \ --maxsize 45000000 \

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Folders_Mapping.txt,v 1.13 2017/05/24 19:18:41 gilles Exp gilles $ $Id: FAQ.Folders_Mapping.txt,v 1.15 2017/11/13 00:01:14 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -12,7 +12,19 @@ the prefix and the separator which are automatically adapted
for host2. for host2.
Before using --regextrans2 you should consider using --automap Before using --regextrans2 you should consider using --automap
and -f1f2 because they are simpler to understand and use. and --f1f2 because they are simpler to understand and use.
--automap : guesses folders mapping, for folders like
"Sent", "Junk", "Drafts", "All", "Archive", "Flagged".
--f1f2 str1=str2 : Force folder str1 to be synced to str2,
--f1f2 overrides --automap and --regextrans2.
--subfolder2 str : Move whole host1 folders hierarchy under this
host2 folder str .
It does it by adding two --regextrans2 options before
all others. Add --debug to see what's really going on.
Things to know and understand before playing with --regextrans2 Things to know and understand before playing with --regextrans2

View File

@ -0,0 +1,24 @@
#!/bin/cat
$Id: FAQ.Folders_Sizes.txt,v 1.1 2017/09/29 11:10:53 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc
=======================================================================
Imapsync tips to know folders sizes.
=======================================================================
=======================================================================
Q. How can I know the size of all folders before launching a sync?
R. Use --justfoldersizes option.
With --justfoldersizes option, imapsync displays the folder size
part of a run and then exits without doing any transfer:
imapsync ... --justfoldersizes
=======================================================================
=======================================================================

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: FAQ.General.txt,v 1.233 2017/09/07 22:08:42 gilles Exp gilles $ # $Id: FAQ.General.txt,v 1.238 2018/03/07 04:26:04 gilles Exp gilles $
======================================================================= =======================================================================
General FAQ for imapsync General FAQ for imapsync
@ -9,7 +9,7 @@ This document is also available at
https://imapsync.lamiral.info/#doc https://imapsync.lamiral.info/#doc
https://imapsync.lamiral.info/FAQ.d/FAQ.General.txt https://imapsync.lamiral.info/FAQ.d/FAQ.General.txt
Questions anwswered in this FAQ are: Questions answered in this FAQ are:
Q. Do I need to create IMAP mailboxes at the destination platform? Q. Do I need to create IMAP mailboxes at the destination platform?
@ -55,8 +55,6 @@ Q. How can I use imapsync with Mail::IMAPClient 2.2.9 perl module?
Q. How to verify imapsync.exe I got is the right file bit per bit? Q. How to verify imapsync.exe I got is the right file bit per bit?
Q. Can I use imapsync to migrate emails from pop3 server to imap server?
Q. Folders are not created on host2. What happens? Q. Folders are not created on host2. What happens?
Q. I am interested in creating a local clone of the IMAP on a LAN Q. I am interested in creating a local clone of the IMAP on a LAN
@ -112,6 +110,7 @@ Q: How can I write an .rpm with imapsync
Q. Where I can read up on the various IMAP RFCs? Q. Where I can read up on the various IMAP RFCs?
Now the questions again with their answers.
======================================================================= =======================================================================
Q. Do I need to create IMAP mailboxes at the destination platform? Q. Do I need to create IMAP mailboxes at the destination platform?
@ -225,14 +224,12 @@ users who bought the support get my help first.
======================================================================= =======================================================================
Q. Where I can find old imapsync releases? Q. Where I can find old imapsync releases?
R. https://imapsync.lamiral.info/dist/old_releases/ R. Search the internet or ask the author.
======================================================================= =======================================================================
Q. Where I can find free open and gratis imapsync releases? Q. Where I can find free open and gratis imapsync releases?
R. https://imapsync.lamiral.info/dist/ R. Search the internet or ask the author.
Github has a copy at
https://github.com/imapsync/imapsync
Q. Is is legal to find imapsync gratis (or not) elsewhere? Q. Is is legal to find imapsync gratis (or not) elsewhere?
@ -297,12 +294,6 @@ R. Add also --noexpungeaftereach if you use --delete.
imapsync ... --delete --noexpunge --noexpungeaftereach --expunge2 imapsync ... --delete --noexpunge --noexpungeaftereach --expunge2
R. Add also --nocheckmessageexists
--nocheckmessageexists is on by default since release 1.520.
Since transfer can be long on a huge mailbox imapsync checks
a message exist before copying it, but it takes time and
cpu on the host1 server.
Notes about --useuid Notes about --useuid
Case where building the cache first is necessary (to avoid multiples transfers) Case where building the cache first is necessary (to avoid multiples transfers)
@ -436,19 +427,6 @@ R. Use md5sum to check integrity of the file.
Then compare the checksum with the one given by the author. Then compare the checksum with the one given by the author.
=======================================================================
Q. Can I use imapsync to migrate emails from pop3 server to imap server?
R1. No, but you can migrate emails from a pop3 server to an imap server
with the command line tool pop2imap:
http://www.linux-france.org/prj/pop2imap/
R2. Yes, sometimes, because many pop3 servers runs in parallel
with an imap server on 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. Folders are not created on host2. What happens? Q. Folders are not created on host2. What happens?
@ -774,7 +752,7 @@ R. Here:
RFC 3501 - INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 RFC 3501 - INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1
http://www.faqs.org/rfcs/rfc3501.html http://www.faqs.org/rfcs/rfc3501.html
RFC2683 - IMAP4 Implementation Recommendations RFC 2683 - IMAP4 Implementation Recommendations
http://www.faqs.org/rfcs/rfc2683.html http://www.faqs.org/rfcs/rfc2683.html
RFC 2595 - Using TLS with IMAP, POP3 and ACAP RFC 2595 - Using TLS with IMAP, POP3 and ACAP
@ -786,7 +764,7 @@ http://www.faqs.org/rfcs/rfc2822.html
RFC 2342 - IMAP4 Namespace RFC 2342 - IMAP4 Namespace
http://www.faqs.org/rfcs/rfc2342.html http://www.faqs.org/rfcs/rfc2342.html
RFC2180 - IMAP4 Multi-Accessed Mailbox Practice RFC 2180 - IMAP4 Multi-Accessed Mailbox Practice
http://www.faqs.org/rfcs/rfc2180.html http://www.faqs.org/rfcs/rfc2180.html
RFC 4549 - Synchronization Operations for Disconnected IMAP4 Clients RFC 4549 - Synchronization Operations for Disconnected IMAP4 Clients

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Gmail.txt,v 1.33 2017/09/05 15:11:20 gilles Exp gilles $ $Id: FAQ.Gmail.txt,v 1.37 2018/03/23 19:07:37 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -7,7 +7,7 @@ This documentation is also at http://imapsync.lamiral.info/#doc
Imapsync tips for Gmail accounts. Imapsync tips for Gmail accounts.
======================================================================= =======================================================================
Questions anwswered in this FAQ are: Questions answered in this FAQ are:
Q. Can I use imapsync to transfer from or to Gmail accounts? Q. Can I use imapsync to transfer from or to Gmail accounts?
@ -46,6 +46,9 @@ Q. How to use a Gmail account to backup several different imap accounts?
Q. How to migrate email from gmail to google apps? Q. How to migrate email from gmail to google apps?
Now the questions again with their answers.
======================================================================= =======================================================================
Q. Can I use imapsync to transfer from or to Gmail accounts? Q. Can I use imapsync to transfer from or to Gmail accounts?
@ -84,6 +87,15 @@ Q. How to synchronize from Gmail to Gmail?
R. Use the following example: R. Use the following example:
./imapsync \
--user1 account1@gmail.com \
--password1 gmailsecret1 \
--user2 account2@gmail.com \
--password2 gmailsecret2 \
--gmail12
Or, replacing what does --gmail12:
./imapsync \ ./imapsync \
--host1 imap.gmail.com \ --host1 imap.gmail.com \
--ssl1 \ --ssl1 \
@ -142,6 +154,15 @@ Q. How to synchronize from XXX to Gmail?
R. Use the following example: R. Use the following example:
imapsync --host1 mail.oldhost.com \
--user1 my_email@oldhost.com \
--password1 password \
--user2 my_email@gmail.com \
--password2 password \
--gmail2
Or, replacing what does --gmail2:
imapsync --host1 mail.oldhost.com \ imapsync --host1 mail.oldhost.com \
--user1 my_email@oldhost.com \ --user1 my_email@oldhost.com \
--password1 password \ --password1 password \
@ -223,6 +244,15 @@ Q. How to synchronize from Gmail to XXX?
R. Use this example: R. Use this example:
./imapsync \
--user1 gilles.lamiral@gmail.com \
--password1 gmailsecret \
--host2 localhost \
--user2 tata \
--gmail1
Or, replacing what does --gmail1:
./imapsync \ ./imapsync \
--host1 imap.gmail.com \ --host1 imap.gmail.com \
--user1 gilles.lamiral@gmail.com \ --user1 gilles.lamiral@gmail.com \
@ -237,9 +267,6 @@ R. Use this example:
--automap \ --automap \
--regextrans2 "s,\[Gmail\].,," \ --regextrans2 "s,\[Gmail\].,," \
--skipcrossduplicates \ --skipcrossduplicates \
--folderfirst "Work" \
--folderfirst "Friends" \
--folderlast "CanWait" \
--folderlast "[Gmail]/All Mail" --folderlast "[Gmail]/All Mail"
@ -391,7 +418,8 @@ On Unix:
On Windows: On Windows:
imapsync.exe ... --search "X-GM-RAW ""has:attachment in:unread""" perl imapsync ... --search "X-GM-RAW ""has:attachment in:unread"""
======================================================================= =======================================================================
Q. How to avoid the [IMAP] prefix on Gmail side? Q. How to avoid the [IMAP] prefix on Gmail side?

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Massive.txt,v 1.15 2017/06/17 13:45:15 gilles Exp gilles $ $Id: FAQ.Massive.txt,v 1.17 2017/12/20 03:38:07 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -123,10 +123,17 @@ How many syncs can we run in parallel? here comes measurements.
nload -t 6000 eth0 -u K nload -t 6000 eth0 -u K
Another excellent network tool is dstat: Another good network tool is dstat:
dstat -n -N eth0 6 dstat -n -N eth0 6
A excellent tool for this purpose is iftop, the following
command will monitor imap and imaps connexions
on interfce eth0, only them, and sum them up:
iftop -i eth0 -f 'port imap or port imaps' -B
On Windows, get the overall network rate with the classical On Windows, get the overall network rate with the classical
task manager (Ctrl-Alt-Sup), there is a network tab in it. task manager (Ctrl-Alt-Sup), there is a network tab in it.
Don't hesitate to send me free good tools to measure the Don't hesitate to send me free good tools to measure the
@ -164,14 +171,14 @@ Same thing if they both decrease!
R2. Isolating and overcoming bottlenecks R2. Isolating and overcoming bottlenecks
On any process involving several mechanisms, among all elements taking On any process involving several mechanisms, among all elements taking
part on the process there is always a bottleneck. No one knows in part on the process, there is always a bottleneck. No one knows in
advance what is the first bottleneck. The first bottleneck has to be advance what is the first bottleneck. The first bottleneck has to be
determined, by measurements, not by guesses. Once this first determined, by measurements, not by guesses. Once this first
bottleneck is known and overcome then the next bottleneck has to be bottleneck is known and overcome then the next bottleneck has to be
determined and overcome too, if needed. Repeat the process of looking determined and overcome too, if needed. Repeat the process of looking
for the next bottleneck and its elimination until you estimate the for the next bottleneck and its elimination until you estimate the
transfer rates, money costs and final dates are good enough to proceed transfer rates, money costs, time spent on this, and final dates
the whole huge migration. are good enough to proceed the whole huge migration.
Possible bottlenecks: Possible bottlenecks:
@ -180,7 +187,7 @@ Possible bottlenecks:
For example Gmail, Office365, Exchange have throttle limits. For example Gmail, Office365, Exchange have throttle limits.
- Bandwidth. - Bandwidth.
Usually available bandwidth is not a bottleneck. Usually available bandwidth is NOT a bottleneck.
Meanwhile, it can be a bottleneck on small Internet connexions. Meanwhile, it can be a bottleneck on small Internet connexions.
Imapsync downloads messages from host1 and upload messages to host2, Imapsync downloads messages from host1 and upload messages to host2,
consider this in case the connexion are asymetric. consider this in case the connexion are asymetric.
@ -189,6 +196,11 @@ Possible bottlenecks:
I/O are a classical bottleneck, almost always forgotten. I/O are a classical bottleneck, almost always forgotten.
Unlike CPU and RAM, Input/Output performances don't improve Unlike CPU and RAM, Input/Output performances don't improve
very much as time goes on so it's often a bottleneck. very much as time goes on so it's often a bottleneck.
To measure and overcome an I/O disk bottleneck, you need
usually a direct access to host1 and host2.
An I/O bottleneck where imapsync runs is possible if
--usecache or --useuid is used or with very big messages.
- RAM memory. - RAM memory.
On all sides, monitor that your systems don't swap on disk, On all sides, monitor that your systems don't swap on disk,

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Messages_Selection.txt,v 1.12 2017/09/05 15:11:20 gilles Exp gilles $ $Id: FAQ.Messages_Selection.txt,v 1.13 2018/03/07 04:12:37 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -7,7 +7,7 @@ This documentation is also at http://imapsync.lamiral.info/#doc
Imapsync tips to select messages. Imapsync tips to select messages.
======================================================================= =======================================================================
Questions anwswered in this FAQ are: Questions answered in this FAQ are:
Q. What messages imapsync syncs by default? Q. What messages imapsync syncs by default?

View File

@ -0,0 +1,49 @@
#!/bin/cat
$Id: FAQ.Migration_Plan.txt,v 1.2 2018/03/07 04:28:00 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc
=====================================================================
Imapsync. Suggestions for a good, low impact on users,
well executed email migration plan.
=====================================================================
A good migration plan:
* Create the new mailboxes on the destination server.
* Decrease the TTL of the MX, as well as the imap hostname resolution,
to 5 minutes (or even less). See FAQ.TTL.txt to understand why.
* Presync all the mailboxes from the old to the new server, using different name
that the ones used by the imap software clients (use their IP for example).
Presyncs can usefully be done with --delete2 but never use --delete2 once users
started playing with their new account on host2.
* Decide a migration day/hour
* repeat the presyncs (--delete2) daily until the migration hour.
This repeated process will show how long should take the last sync.
* At the migration hour, cut access to the users to the old server
(by changing the imap hostname to a non-imap server for example).
* Change also the MX (for the new messages arriving in the new imap server).
* Wait 5 minutes.
* Do a last sync exactly like the presyncs, not using the imap hostname.
* Shutdown the old imap server.
Now a fork in the process, depending on the response to the following question:
Will the imap software clients use the exact same
triplet credentials as the old server? hostname/username/password
If the answer is yes (clients use the exact same triplet credentials):
* Change the user imap hostname resolution from the old to the new imap server
* Migration done.
If the answer is no (clients use a different triplet credentials):
* Tell the users the old imap server is down and no longer available.
* Give access to new accounts to the users with their new credential triplet
hostname/username/password (the most similar the best for them).
If the way to contact users is email then you should give this long before
shutting down the old server.
* Migration Done

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.OnlineUI.txt,v 1.1 2017/05/04 23:24:55 gilles Exp gilles $ $Id: FAQ.OnlineUI.txt,v 1.5 2018/05/02 12:22:13 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -8,24 +8,93 @@ This documentation is also at http://imapsync.lamiral.info/#doc
https://imapsync.lamiral.info/X/ https://imapsync.lamiral.info/X/
===================================================================== =====================================================================
Q .Will I have any issues with browser timing out? What happens Questions answered in this FAQ are:
if the connection is closed for whatever reason?
Q. How secure is the online visual user interface /X?
Q. Will I have any issues with browser timing out? What happens
if the browser connection is closed for whatever reason?
Now the questions again with their answers.
=====================================================================
Q. How secure is the online visual user interface /X?
R0. Well, I don't know if asking the provider whether his online
service is secure or not would be of any interest.
Let's do it anyway, you'll be the judge.
R1. Some figures
Date of this report: 8 March 2018.
The online imapsync service /X started 9 January 2017 (422 days of service).
In average, /X has 20 users per day lunching 6 different migrations, from
one launch to many many (hundreds).
The total volume /X transferred is 17 TiB in 48000 email imap migrations.
R2. Pros & Cons
The online imapsync service /X runs on https only, with a
letsencrypt certificate, a certificate overall rated "A" at
https://www.ssllabs.com/ssltest/analyze.html?d=imapsync.lamiral.info
Because of the https usage, what the users enter in their browser,
the imap logins and passwords, can't be eavesdropped on the network.
Imapsync itself cares about encryption for the imap sessions,
if possible: It tries SSL first on port 993, then TLS if the
servers announces TLS, then no encryption. What is done with
an imap server is independent of what is done with the other.
At the date of 8 March 2018, there is no security problem detected
or reported to me (Gilles LAMIRAL) so far.
As the owner of the service, it could have been 48 000 pairs of
credentials collected and nearly 17 terabytes of email messages.
I haven't kept them but I can't prove I haven't. It's just trust,
like nearly every online service in the universe.
The imap server certificates are not checked (by default)
because too many imap servers are crappy configured regarding
certificates.
This default behavior is chosen like this because users of /X
wants their emails transferred, instead of not trasferred because
of an incompetent imap server sysadmin.
Anyway, this part, checking imap ssl/tls certificates, could be
improved from my side by including well known certificates
directly in imapsync.
If the imap servers don't honor ssl nor tls, then logins, passwords
and everything will go clear text during the imap transfers.
That's not good at all but what "comforts" me is that if the
imap servers do only clear text transfer, then it is also true
for all imap sessions the owner of the accounts encounter,
imapsync is just one of them.
Last point, who could be sure no cracker cracked the online host and
currently sniffs the credentials? No one, I'm not sure myself, even
if I do take care of that possibility.
=====================================================================
Q. Will I have any issues with browser timing out? What happens
if the browser connection is closed for whatever reason?
R. It should be ok R. It should be ok
With the /X interface there is two connections (three connections in When using the /X interface there are three connections.
fact but let simplify the picture), 1 is the Browser-WebServer One connection is the Browser-WebServer connection, the
connection, 2 is the WebServer-ImapServers connections (imapsync two others are the WebServer-ImapServers connections (imapsync stuff).
stuff).
If the Browser-WebServer connection is timeout (but it shouldn't If the Browser-WebServer connection is timeout (but it shouldn't
because of the log refresh), the imapsync sync might continue because of the log refresh), the imapsync sync might continue
anyway. To see if it continues or not, just do a sync again and the anyway. To see if it continues or not, just do a sync again and the
interface will tell you that a sync is already going on, if the interface will tell you that a sync is already going on, if the
"Sync!" button is grey/inactive then just reload the page (F5 or "Sync!" button is gray/inactive then just reload the page (F5 or
similar). similar), and reenter the credentials.
Anyway, on the /X you can try to do several parallel runs on the same By the way, on the /X you can try to do several parallel runs on the same
mailbox even if there is no timeout, open a new tab/windows with /X mailbox even if there is no timeout, open a new tab/windows with /X
and start a same sync, it's safe, the /X will say, if any, that there and start a same sync, it's safe, the /X will say, if any, that there
is already a current sync. is already a current sync.
@ -34,3 +103,6 @@ You can stop this sync with the "Abort!" button from any /X
tab/window, even from another browser or place. To doing this with tab/window, even from another browser or place. To doing this with
success, you have to give the same account parameters, same success, you have to give the same account parameters, same
credentials, or imapsync will ignore the demand. credentials, or imapsync will ignore the demand.
=====================================================================
=====================================================================

60
FAQ.d/FAQ.POP3.txt Normal file
View File

@ -0,0 +1,60 @@
#!/bin/cat
$Id: FAQ.POP3.txt,v 1.2 2018/02/02 20:32:19 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc
=======================================================================
Imapsync tips about POP3.
=======================================================================
Questions answered here are:
Q. Can I use imapsync to migrate emails from pop3 server to imap server?
Q. How can I handle those terrible POP-leaving-a-copy users?
POP-leaving-a-copy clients will download a new copy of all
their emails after a migration, which is a big pain and
causes hundreds of support calls.
=======================================================================
Q. Can I use imapsync to migrate emails from pop3 server to imap server?
R1. No, but you can migrate emails from a pop3 server to an imap server
with the command line tool pop2imap:
http://www.linux-france.org/prj/pop2imap/
R2. Yes, sometimes, because many pop3 servers runs in parallel
with an imap server on 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. How can I handle those terrible POP-leaving-a-copy users?
POP-leaving-a-copy clients will download a new copy of all
their emails after a migration, which is a big pain and
causes hundreds of support calls.
R. A discussion about this issue
http://www.linux-france.org/prj/imapsync_list/msg02622.html
http://www.linux-france.org/prj/imapsync_list/msg02623.html
My reply was not very good
http://www.linux-france.org/prj/imapsync_list/msg02624.html
It's because I wrote pop2imap and it uses a stateless
mechanism to avoid duplicates, I wasn't aware of UIDL.
Here is a better response to handle and fix this problem, I hope:
If the pop mailboxes are known and known to be regularly fetched, then
all the INBOX messages, or at least the "old" ones, can be moved in an
subfolder INBOX_back. It requires to have "access" to the POP
sessions. The POP server log file is usually enough to know which
account opened a pop connection, and when.
See also Rick Sanders discussion about this issue:
https://www.emailquestions.com/threads/how-to-prevent-duplicate-emails-after-server-migration-for-pop3-users-with-leave-mail-on-server.8109/
=======================================================================
=======================================================================

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Release_Checklist.txt,v 1.5 2017/09/07 12:38:45 gilles Exp gilles $ $Id: FAQ.Release_Checklist.txt,v 1.6 2017/09/16 20:21:39 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -20,3 +20,8 @@ Checklist before release a new release:
m4 -P W/ml_announce.in m4 -P W/ml_announce.in
- Review the general FAQ.d/FAQ.General.txt - Review the general FAQ.d/FAQ.General.txt
- make dist
- make publish
- verify VERSION is uploaded

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.Reporting_Bugs.txt,v 1.2 2017/09/07 12:10:49 gilles Exp gilles $ $Id: FAQ.Reporting_Bugs.txt,v 1.3 2018/04/10 00:17:18 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -13,7 +13,7 @@ Q. How can I report bugs or problems I encountered with Imapsync?
R. Help me to help you: follow the following guidelines. R. Help me to help you: follow the following guidelines.
Report any bug or feature request directly to the author by Report any bug or feature request directly to the author by
email at <gilles.lamiral@laposte.net> email at <gilles@lamiral.info>
Put a useful title with word "imapsync" in it: my spam filters Put a useful title with word "imapsync" in it: my spam filters
won't filter it. won't filter it.

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.SSL_errors.txt,v 1.1 2017/05/24 19:16:40 gilles Exp gilles $ $Id: FAQ.SSL_errors.txt,v 1.5 2018/04/25 17:58:12 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -7,23 +7,26 @@ This documentation is also at http://imapsync.lamiral.info/#doc
Imapsync SSL errors Imapsync SSL errors
===================================================== =====================================================
Questions anwswered in this FAQ are: Questions answered in this FAQ are:
Q. What are the errors Q. What are the errors
DEBUG: .../IO/Socket/SSL.pm:1165: local error: SSL write error DEBUG: .../IO/Socket/SSL.pm:1165: local error: SSL write error
or or
DEBUG: .../IO/Socket/SSL.pm:1088: local error: SSL read error DEBUG: .../IO/Socket/SSL.pm:1088: local error: SSL read error
Q. What can I do to avoid those "SSL read/write errors"? Q. What can I do to avoid those "SSL read/write errors"?
Q. SSL connect attempt failed SSL
routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
======================================================================= =======================================================================
Q. What are the errors Q. What are the errors
DEBUG: .../IO/Socket/SSL.pm:1165: local error: SSL write error DEBUG: .../IO/Socket/SSL.pm:1165: local error: SSL write error
or or
DEBUG: .../IO/Socket/SSL.pm:1088: local error: SSL read error DEBUG: .../IO/Socket/SSL.pm:1088: local error: SSL read error
R. Like they claim, those errors are SSL errors. SSL is not directly
R1.Like they claim, those errors are SSL errors. SSL is not directly
done by imapsync but by an underlying Perl module called done by imapsync but by an underlying Perl module called
IO::Socket::SSL. Those errors arise sometimes and sometimes IO::Socket::SSL. Those errors arise sometimes and sometimes
they form a serie that ends with imapsync auto-abortion. they form a serie that ends with imapsync auto-abortion.
@ -35,6 +38,9 @@ R. Like they claim, those errors are SSL errors. SSL is not directly
======================================================================= =======================================================================
Q. What can I do to avoid those "SSL read/write errors"? Q. What can I do to avoid those "SSL read/write errors"?
R0. Windows users: upgrade to imapsync.exe release 1.836 (or next ones)
Those errors don't appear with recent releases, post 1.836
R1. Remove all ssl/tls encryption R1. Remove all ssl/tls encryption
imapsync ... --nossl1 --notls1 --nossl2 --notls2 imapsync ... --nossl1 --notls1 --nossl2 --notls2
@ -48,9 +54,28 @@ R3. Run imapsync on a Linux machine, a VM is ok, there are less
SSL errors on Unix. SSL errors on Unix.
R4. Use https://imapsync.lamiral.info/X/ R4. Use https://imapsync.lamiral.info/X/
It's a Linux host so R3 applies there. It's a Linux host so response R3 applies there.
R5. Set up a ssltunnel proxy to the host. R5. Set up a ssltunnel proxy to the host.
Read the file FAQ.Security.txt Read the file FAQ.Security.txt for an example to set up
a ssltunnel proxy.
======================================================================= =======================================================================
Q. SSL connect attempt failed SSL
routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
R. Use:
imapsync ... --sslargs1 'SSL_cipher_list=DEFAULT'
or
imapsync ... --sslargs2 'SSL_cipher_list=DEFAULT'
depending on where the error occurs, host1 or host2 or both.
=======================================================================
=======================================================================
=======================================================================

View File

@ -1,5 +1,5 @@
$Id: FAQ.Use_cache.txt,v 1.4 2017/02/14 17:35:22 gilles Exp gilles $ $Id: FAQ.Use_cache.txt,v 1.6 2018/03/07 04:12:37 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -7,13 +7,13 @@ This documentation is also at http://imapsync.lamiral.info/#doc
Imapsync --usecache option Imapsync --usecache option
============================================ ============================================
Questions anwswered in this FAQ are: Questions answered in this FAQ are:
Q. On Windows, with --useuid or --usecache a problem occurs with long Q. On Windows, with --useuid or --usecache a problem occurs with long
nested folder names. The error message is: nested folder names. The error message is:
"No such file or directory; The filename or extension is too long" "No such file or directory; The filename or extension is too long"
Q. Inode problem with --usecache on Linux Q. Inode problem with --usecache or --useuid on Linux
Questions and their answers: Questions and their answers:
@ -68,7 +68,7 @@ Fixing this long path problem directly in imapsync is in the TODO file
for a very long time. for a very long time.
======================================================================= =======================================================================
Q. Inode problem with --usecache on Linux Q. Inode problem with --usecache or --useuid on Linux
R. You may run out of inodes using --usecache, especially with large R. You may run out of inodes using --usecache, especially with large
migration. Option --usecache creates a empty file per email message migration. Option --usecache creates a empty file per email message

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
$Id: FAQ.User_Concurrent_Access.txt,v 1.2 2017/01/06 14:11:13 gilles Exp gilles $ $Id: FAQ.User_Concurrent_Access.txt,v 1.4 2017/12/19 14:55:36 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -14,23 +14,30 @@ R. Think all potential problems with a sync between
a master/source/host1 and a slave/destination/host2 a master/source/host1 and a slave/destination/host2
What happens when a user access syncing accounts depends What happens when a user access syncing accounts depends
on what he does, where he does and when: on what he does, where he does and when.
* Reading: no problem anywhere, anytime. As a summary, reading is safe, writing/deleting is not.
Details:
* Reading: no problem anywhere, at source/host1 or at destination/host2,
anytime. Reading is safe.
* Writing at source/host1: * Writing at source/host1:
* adding folder => will need a resync after * adding folder => will need a resync after
* deleting folder => deletion not synced unless --delete2folders * deleting folder => folders deletions are not synced unless --delete2folders
* deleting message => deletion not synced unless --delete2 * deleting message => messages deletions are not synced unless --delete2
* adding message => will need a resync * adding message => will need a resync
* moving message => will need a resync. Moving is like adding + deleting
so --delete2 is needed to sync the deletion.
* message flag change => will need a resync * message flag change => will need a resync
* Writing at destination/host2: * Writing at destination/host2:
* adding folder => no problem, unless --delete2folders is used * adding folder => no problem, unless --delete2folders is used
* deleting folder => might reappear by the sync * deleting folder => will reappear by a new sync
* adding message => no problem, unless --delete2 is used * adding message => no problem, unless --delete2 is used on next sync.
* deleting message => might reappear by the sync * deleting message => might reappear by a new sync.
* message flag change => might be canceled by the sync * message flag change => will be reseted by a new sync.
======================================================================= =======================================================================
======================================================================= =======================================================================

View File

@ -1,5 +1,5 @@
$Id: FAQ.Virus.txt,v 1.2 2017/07/03 19:30:19 gilles Exp gilles $ $Id: FAQ.Virus.txt,v 1.4 2018/03/21 16:18:53 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -11,7 +11,7 @@ This documentation is also at http://imapsync.lamiral.info/#doc
Q. My virus scanner claims imapsync.exe is a virus/malware/trojan etc. Q. My virus scanner claims imapsync.exe is a virus/malware/trojan etc.
What the hell? What the hell?
R. Yes, I found the same. Two antivirus, Baidu and Jiangmin, report that R1. Yes, I found the same. Two antivirus, Baidu and Jiangmin, report that
imapsync might have a trojan in it. imapsync might have a trojan in it.
All others virus scanner say imapsync.exe is ok. All others virus scanner say imapsync.exe is ok.
I've done this test on imapsync.exe release 1.727 on the two following I've done this test on imapsync.exe release 1.727 on the two following
@ -27,8 +27,17 @@ R2. Explanation:
Any other explanation is welcome! Any other explanation is welcome!
R3. There is no virus alerts reported for the Perl script imapsync R3. There is no virus alerts reported for the Perl script imapsync
itself. The binary imapsync.exe is just a compiled version of itself. The binary imapsync.exe is just a compiled version of
the script imapsync, with perl interpreter itself and all modules the script imapsync, with perl interpreter itself and all modules
needed by imapsync in order to make imapsync.exe a standalone software. needed by imapsync in order to make imapsync.exe a standalone software.
R4. imapsync.exe release 1.836 is reported as totally clean by both
https://www.virustotal.com/
https://www.virustotal.com/#/file/2a33eb93198da77677a4013a5dfb4868cb6aa8f4513e2102a55884b258d19043/detection
and https://metadefender.opswat.com/
https://metadefender.opswat.com/results#!/file/ZTE4MDMxN1MxZTk4aGhxdEdCSlpxVTJoOVlN/regular/information

View File

@ -1,5 +1,5 @@
$Id: FAQ.Yahoo.txt,v 1.6 2017/06/17 14:42:01 gilles Exp gilles $ $Id: FAQ.Yahoo.txt,v 1.7 2017/12/18 10:45:00 gilles Exp gilles $
This documentation is also at http://imapsync.lamiral.info/#doc This documentation is also at http://imapsync.lamiral.info/#doc
@ -20,10 +20,28 @@ R. Use --host1 imap.mail.yahoo.com --ssl1
--ssl1 \ --ssl1 \
--host2 XXX \ --host2 XXX \
--user2 billy \ --user2 billy \
--password2 secret --password2 secret \
--noabletosearch --errorsmax 10000
SSL is mandatory for yahoo since November 2011. SSL is mandatory for yahoo since November 2011.
Why increasing --errorsmax to 10000?
Because during the sync you may encounter several lines like this one:
- msg Inbox/12600 {0} S[36012] F[] I[27-Nov-2015 07:08:35 +0000] could not be fetched: 190 NO [UNAVAILABLE] UID FETCH Server error while fetching messages
- msg Inbox/12600 skipped.
I don't know why it happens, why Yahoo server says
"NO [UNAVAILABLE] UID FETCH Server error while fetching messages"
Usually another run syncs the message successfully.
Why --noabletosearch option?
Yahoo IMAP does not honor well the SEARCH imap command (Dec 2017).
So don't use the --search option.
You can use --minage or/and --maxage but then add also --noabletosearch
Yahoo bandwidth per connexion is relatively low, 50 KiB/s to 500 KiB/s max, usually 100 KiB/s.
Consider using --useuid to speed up large accounts.
You also need to go to Yahoo, security and enable You also need to go to Yahoo, security and enable
"Allow less secure apps to login", "Allow less secure apps to login",
otherwise the login will not work. otherwise the login will not work.

View File

@ -1,5 +1,5 @@
# $Id: htaccess.txt,v 1.18 2017/09/03 03:14:48 gilles Exp gilles $ # $Id: htaccess.txt,v 1.20 2018/03/17 16:12:54 gilles Exp gilles $
AddDescription "<b>Back to Imapsync main page</b>." .. AddDescription "<b>Back to Imapsync main page</b>." ..
@ -16,22 +16,32 @@ AddDescription "<b>Emptying</b> an account." FAQ.Emptying.
AddDescription "<b>Exchange 20xx</b> and <b>Office365</b>." FAQ.Exchange.txt AddDescription "<b>Exchange 20xx</b> and <b>Office365</b>." FAQ.Exchange.txt
AddDescription "<b>Changing folders names</b>." FAQ.Folders_Mapping.txt AddDescription "<b>Changing folders names</b>." FAQ.Folders_Mapping.txt
AddDescription "<b>Selecting folders</b>." FAQ.Folders_Selection.txt AddDescription "<b>Selecting folders</b>." FAQ.Folders_Selection.txt
AddDescription "<b>Folders sizes with Imapsync</b>." FAQ.Folders_Sizes.txt
AddDescription "<b>Flags</b>." FAQ.Flags.txt AddDescription "<b>Flags</b>." FAQ.Flags.txt
AddDescription "<b>General</b> and <b>pot-pourri</b> issues" FAQ.General.txt AddDescription "<b>General</b> and <b>pot-pourri</b> issues" FAQ.General.txt
AddDescription "<b>Gmail</b> accounts." FAQ.Gmail.txt AddDescription "<b>Gmail</b> accounts." FAQ.Gmail.txt
AddDescription "<b>ISP tips</b>." FAQ.ISP.txt AddDescription "<b>ISP tips</b>." FAQ.ISP.txt
AddDescription "<b>Massive/bulk migrations</b>." FAQ.Massive.txt AddDescription "<b>Massive/bulk migrations</b>." FAQ.Massive.txt
AddDescription "<b>Memory issues</b>." FAQ.Memory.txt AddDescription "<b>Memory issues</b>." FAQ.Memory.txt
AddDescription "<b>Migration Plan</b>." FAQ.Migration_Plan.txt
AddDescription "<b>The Online UI service Q&R</b>." FAQ.OnlineUI.txt
AddDescription "<b>Password & special characters on Windows</b>." FAQ.Passwords_on_Windows.txt AddDescription "<b>Password & special characters on Windows</b>." FAQ.Passwords_on_Windows.txt
AddDescription "<b>Password & special characters on Unix</b>." FAQ.Passwords_on_Unix.txt AddDescription "<b>Password & special characters on Unix</b>." FAQ.Passwords_on_Unix.txt
AddDescription "<b>POP3 issues</b>." FAQ.POP3.txt
AddDescription "<b>Selecting messages</b>." FAQ.Messages_Selection.txt AddDescription "<b>Selecting messages</b>." FAQ.Messages_Selection.txt
AddDescription "<b>Oracle-UCS</b>." FAQ.Oracle-UCS.txt AddDescription "<b>Oracle-UCS</b>." FAQ.Oracle-UCS.txt
AddDescription "<b>Checklist before release a new release</b>." FAQ.Release_Checklist.txt
AddDescription "<b>Guidelines to report bugs</b>." FAQ.Reporting_Bugs.txt AddDescription "<b>Guidelines to report bugs</b>." FAQ.Reporting_Bugs.txt
AddDescription "<b>Security</b>." FAQ.Security.txt AddDescription "<b>Security</b>." FAQ.Security.txt
AddDescription "<b>SSL errors</b>." FAQ.SSL_errors.txt AddDescription "<b>SSL errors</b>." FAQ.SSL_errors.txt
AddDescription "<b>SmarterMail</b>." FAQ.SmarterMail.txt AddDescription "<b>SmarterMail</b>." FAQ.SmarterMail.txt
AddDescription "<b>TTL (Time To Live) delay in DNS configuration</b>." FAQ.TTL.txt
AddDescription "<b>Option --usecache and inodes</b>." FAQ.Use_cache.txt AddDescription "<b>Option --usecache and inodes</b>." FAQ.Use_cache.txt
AddDescription "<b>User concurrent access</b>." FAQ.User_Concurrent_Access.txt AddDescription "<b>User concurrent access</b>." FAQ.User_Concurrent_Access.txt
AddDescription "<b>Virus scanners on Imapsync</b>." FAQ.Virus.txt
AddDescription "<b>Why use --addheader?</b>." FAQ.Use_addheader.txt AddDescription "<b>Why use --addheader?</b>." FAQ.Use_addheader.txt
AddDescription "<b>Various imap server</b> softwares." FAQ.Various_Server_Softwares.txt AddDescription "<b>Various imap server</b> softwares." FAQ.Various_Server_Softwares.txt
AddDescription "<b>XOAUTH2</b> (<b>Gmail</b>)." FAQ.XOAUTH2.txt AddDescription "<b>XOAUTH2</b> (<b>Gmail</b>)." FAQ.XOAUTH2.txt

4
FAQ.d/memo Normal file
View File

@ -0,0 +1,4 @@
( cd .. && make upload_FAQ )

View File

@ -1,4 +1,4 @@
# $Id: INSTALL.ANY.txt,v 1.55 2017/04/18 15:11:29 gilles Exp gilles $ # $Id: INSTALL.ANY.txt,v 1.57 2018/02/11 13:35:14 gilles Exp gilles $
# #
# This is the main INSTALL file for imapsync. # This is the main INSTALL file for imapsync.
# imapsync : IMAP sync and migrate tool. # imapsync : IMAP sync and migrate tool.
@ -23,7 +23,7 @@ https://imapsync.lamiral.info/README_Windows.txt
================================= =================================
There are specific INSTALL files in the imapsync directory INSTALL.d/ There are specific INSTALL files in the imapsync directory INSTALL.d/
also available at https://imapsync.lamiral.info/INSTALL.d/ Those documents are also available at https://imapsync.lamiral.info/INSTALL.d/
- Mac OS X - Mac OS X
- FreeBSD - FreeBSD
@ -32,6 +32,7 @@ also available at https://imapsync.lamiral.info/INSTALL.d/
- Debian - Debian
- Ubuntu - Ubuntu
- AWS EC2 - AWS EC2
- Online UI like /X
If you are not on one of these systems then read the section If you are not on one of these systems then read the section
below called "Installing imapsync on other Unixes". below called "Installing imapsync on other Unixes".
@ -42,7 +43,7 @@ below called "Installing imapsync on other Unixes".
Easy. Easy.
Read the file INSTALL.d/INSTALL.Darwin.txt Read the file INSTALL.d/INSTALL.Darwin.txt
Also available at This document is also available at
https://imapsync.lamiral.info/INSTALL.d/INSTALL.Darwin.txt https://imapsync.lamiral.info/INSTALL.d/INSTALL.Darwin.txt
===================================== =====================================
@ -51,7 +52,7 @@ https://imapsync.lamiral.info/INSTALL.d/INSTALL.Darwin.txt
Easy. Easy.
Read the file INSTALL.d/INSTALL.FreeBSD.txt Read the file INSTALL.d/INSTALL.FreeBSD.txt
Also available at This document is also available at
https://imapsync.lamiral.info/INSTALL.d/INSTALL.FreeBSD.txt https://imapsync.lamiral.info/INSTALL.d/INSTALL.FreeBSD.txt
@ -61,7 +62,7 @@ https://imapsync.lamiral.info/INSTALL.d/INSTALL.FreeBSD.txt
Easy. Easy.
Read the file INSTALL.d/INSTALL.Centos.txt Read the file INSTALL.d/INSTALL.Centos.txt
Also available at This document is also available at
https://imapsync.lamiral.info/INSTALL.d/INSTALL.Centos.txt https://imapsync.lamiral.info/INSTALL.d/INSTALL.Centos.txt
@ -71,7 +72,7 @@ https://imapsync.lamiral.info/INSTALL.d/INSTALL.Centos.txt
Easy. Easy.
Read the file INSTALL.d/INSTALL.CPanel.txt Read the file INSTALL.d/INSTALL.CPanel.txt
Also available at This document is also available at
https://imapsync.lamiral.info/INSTALL.d/INSTALL.CPanel.txt https://imapsync.lamiral.info/INSTALL.d/INSTALL.CPanel.txt
@ -81,7 +82,7 @@ https://imapsync.lamiral.info/INSTALL.d/INSTALL.CPanel.txt
Not so easy. Not so easy.
See the file INSTALL.d/INSTALL.Debian.txt See the file INSTALL.d/INSTALL.Debian.txt
Also available at This document is also available at
https://imapsync.lamiral.info/INSTALL.d/INSTALL.Debian.txt https://imapsync.lamiral.info/INSTALL.d/INSTALL.Debian.txt
============================================ ============================================
@ -90,7 +91,7 @@ https://imapsync.lamiral.info/INSTALL.d/INSTALL.Debian.txt
Not so easy. Not so easy.
See the file INSTALL.d/INSTALL.Ubuntu.txt See the file INSTALL.d/INSTALL.Ubuntu.txt
Also available at This document is also available at
https://imapsync.lamiral.info/INSTALL.d/INSTALL.Ubuntu.txt https://imapsync.lamiral.info/INSTALL.d/INSTALL.Ubuntu.txt
================================== ==================================
@ -99,9 +100,17 @@ https://imapsync.lamiral.info/INSTALL.d/INSTALL.Ubuntu.txt
Not so easy. Not so easy.
See the file INSTALL.d/INSTALL.AWS_EC2.txt See the file INSTALL.d/INSTALL.AWS_EC2.txt
Also available at This document is also available at
https://imapsync.lamiral.info/INSTALL.d/INSTALL.AWS_EC2.txt https://imapsync.lamiral.info/INSTALL.d/INSTALL.AWS_EC2.txt
======================================
= Installing imapsync online like /X =
======================================
Follow the document INSTALL.d/INSTALL.OnlineUI.txt
This document is also available at
https://imapsync.lamiral.info/INSTALL.d/INSTALL.OnlineUI.txt
========================================= =========================================
== Installing imapsync on other Unixes == == Installing imapsync on other Unixes ==

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.AWS_EC2.txt,v 1.3 2017/04/18 15:06:35 gilles Exp gilles $ # $Id: INSTALL.AWS_EC2.txt,v 1.4 2017/11/19 07:50:24 gilles Exp gilles $
================================== ==================================
= Installing imapsync on AWS EC2 = = Installing imapsync on AWS EC2 =
@ -12,37 +12,38 @@ Amazon Linux AMI release 2017.03
sudo yum install \ sudo yum install \
perl-Class-Load-0.20-3.6.amzn1.noarch \ perl-Class-Load \
perl-IO-Compress-2.061-2.12.amzn1.noarch \ perl-IO-Compress \
perl-Crypt-OpenSSL-RSA-0.28-7.8.amzn1.x86_64 \ perl-Crypt-OpenSSL-RSA \
perl-Data-Dumper-2.145-3.5.amzn1.x86_64 \ perl-Data-Dumper \
perl-Dist-CheckConflicts-0.06-2.5.amzn1.noarch \ perl-Dist-CheckConflicts \
perl-File-Copy-Recursive-0.38-14.8.amzn1.noarch \ perl-File-Copy-Recursive \
perl-IO-Socket-INET6-2.69-5.8.amzn1.noarch \ perl-IO-Socket-INET6 \
perl-IO-Socket-SSL-1.94-3.13.amzn1.noarch \ perl-IO-Socket-SSL \
perl-JSON-2.59-2.8.amzn1.noarch \ perl-JSON \
perl-HTML-Parser-3.71-4.7.amzn1.x86_64 \ perl-HTML-Parser \
perl-libwww-perl-6.05-2.17.amzn1.noarch \ perl-libwww-perl \
perl-Mail-IMAPClient-3.34-1.2.amzn1.noarch \ perl-Mail-IMAPClient \
perl-Module-Implementation-0.06-6.6.amzn1.noarch \ perl-Module-Implementation \
perl-Module-Runtime-0.013-4.5.amzn1.noarch \ perl-Module-Runtime \
perl-Module-ScanDeps-1.10-3.7.amzn1.noarch \ perl-Module-ScanDeps \
perl-Net-SSLeay-1.65-2.10.amzn1.x86_64 \ perl-Net-SSLeay \
perl-Package-Stash-0.34-2.6.amzn1.noarch \ perl-Package-Stash \
perl-Package-Stash-XS-0.26-3.7.amzn1.x86_64 \ perl-Package-Stash-XS \
perl-Parse-RecDescent-1.967009-5.13.amzn1.noarch \ perl-Parse-RecDescent \
perl-Readonly-1.03-22.8.amzn1.noarch \ perl-Readonly \
perl-Sys-MemInfo-0.91-7.5.amzn1.x86_64 \ perl-Regexp-Common \
perl-TermReadKey-2.30-20.9.amzn1.x86_64 \ perl-Sys-MemInfo \
perl-Test-Fatal-0.010-5.5.amzn1.noarch \ perl-TermReadKey \
perl-Test-MockObject-1.20120301-3.8.amzn1.noarch \ perl-Test-Fatal \
perl-Test-Simple-0.98-243.6.amzn1.noarch \ perl-Test-MockObject \
perl-Test-Pod-1.48-3.9.amzn1.noarch \ perl-Test-Simple \
perl-Test-Requires-0.06-10.6.amzn1.noarch \ perl-Test-Pod \
perl-Try-Tiny-0.12-2.5.amzn1.noarch \ perl-Test-Requires \
perl-Unicode-String-2.09-29.7.amzn1.x86_64 \ perl-Try-Tiny \
perl-URI-1.60-9.8.amzn1.noarch \ perl-Unicode-String \
perl-ExtUtils-Embed-1.30-286.38.amzn1.noarch \ perl-URI \
perl-ExtUtils-Embed \
cpanminus cpanminus
sudo cpanm Authen::NTLM Data::Uniqid IO::Tee JSON::WebToken JSON::WebToken::Crypt::RSA Test::Mock::Guard sudo cpanm Authen::NTLM Data::Uniqid IO::Tee JSON::WebToken JSON::WebToken::Crypt::RSA Test::Mock::Guard

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.Centos.txt,v 1.6 2016/11/07 10:40:53 gilles Exp gilles $ # $Id: INSTALL.Centos.txt,v 1.7 2018/04/24 00:15:32 gilles Exp gilles $
================================= =================================
= Installing imapsync on CentOS = = Installing imapsync on CentOS =
@ -32,6 +32,48 @@ Unit tests:
imapsync --tests imapsync --tests
==================================
== Centos 7 and latest imapsync ==
==================================
At the time of this writing (April 2018), the epel repository contains
imapsync release 1.727, which is not the latest available release.
In order to install the latest imapsync I suggest the following process:
Install the epel imapsync 1.727 release via yum like mentioned above.
It will install many needed packages, Perl itself and Perl modules
for release 1.727. The latest imapsync needs more Perl modules.
Then:
yum install perl-App-cpanminus \
perl-Dist-CheckConflicts \
perl-HTML-Parser \
perl-libwww-perl \
perl-Module-Implementation \
perl-Module-ScanDeps \
perl-Package-Stash \
perl-Package-Stash-XS \
perl-PAR-Packer \
perl-Regexp-Common \
perl-Sys-MemInfo \
perl-Test-Fatal \
perl-Test-Mock-Guard \
perl-Test-Requires \
perl-Test-NoWarnings \
perl-Test-Deep \
perl-Test-Warn \
perl-Try-Tiny
wget https://imapsync.lamiral.info/imapsync
chmod +x imapsync
./imapsync --testslive
Now you have the latest imapsync on Centos 7.
============== ==============
== Centos 6 == == Centos 6 ==
============== ==============

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.Darwin.txt,v 1.16 2016/11/07 05:06:34 gilles Exp gilles $ # $Id: INSTALL.Darwin.txt,v 1.17 2017/11/30 02:10:27 gilles Exp gilles $
=================================================== ===================================================
= Installing imapsync binary on Darwin / Mac OS X = = Installing imapsync binary on Darwin / Mac OS X =
@ -117,7 +117,6 @@ Now imapsync should work on your system.
= Building imapsync binary on Darwin / Mac OS X = = Building imapsync binary on Darwin / Mac OS X =
================================================= =================================================
cpanm Module::ScanDeps
cpanm Module::ScanDeps cpanm Module::ScanDeps
cpanm PAR::Packer cpanm PAR::Packer

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.Debian.txt,v 1.15 2017/04/05 02:03:04 gilles Exp gilles $ # $Id: INSTALL.Debian.txt,v 1.21 2018/05/06 15:03:04 gilles Exp gilles $
There is three install sections in this document, There is three install sections in this document,
one for Debian 9 Stretch one for Debian 9 Stretch
@ -13,7 +13,6 @@ It could be in Debian nowadays, as always, my last words on this discussion were
"Do what you want, I promise I won't complain anymore about the fact imapsync is on Debian or not." "Do what you want, I promise I won't complain anymore about the fact imapsync is on Debian or not."
https://lists.debian.org/debian-legal/2011/01/msg00058.html https://lists.debian.org/debian-legal/2011/01/msg00058.html
The license is now "No limits to do anything with this work and this license". The license is now "No limits to do anything with this work and this license".
and full dist/ is back to https://imapsync.lamiral.info/dist/
Feel free. Feel free.
See also a more detailed story at See also a more detailed story at
https://lists.debian.org/debian-user/2016/11/msg00849.html https://lists.debian.org/debian-user/2016/11/msg00849.html
@ -24,31 +23,43 @@ https://lists.debian.org/debian-user/2016/11/msg00849.html
=========================================== ===========================================
Here is the command to install imapsync dependencies. Here is the command to install imapsync dependencies.
You need root priviledge to run it. The repositories are the classical ones, ie, a
sources.list file with:
apt install -y \ deb http://deb.debian.org/debian stretch main contrib
libjson-webtoken-perl \
libauthen-ntlm-perl \ You need root privilege to run it, be root or use sudo.
libcgi-pm-perl \
libcrypt-openssl-rsa-perl \ apt install -y \
libdata-uniqid-perl \ libjson-webtoken-perl \
libauthen-ntlm-perl \
libcgi-pm-perl \
libcrypt-openssl-rsa-perl \
libdata-uniqid-perl \
libfile-copy-recursive-perl \ libfile-copy-recursive-perl \
libio-socket-inet6-perl \ libio-socket-inet6-perl \
libio-socket-ssl-perl \ libio-socket-ssl-perl \
libio-tee-perl \ libio-tee-perl \
libhtml-parser-perl \ libhtml-parser-perl \
libjson-webtoken-perl \ libjson-webtoken-perl \
libmail-imapclient-perl \ libmail-imapclient-perl \
libparse-recdescent-perl \ libparse-recdescent-perl \
libmodule-scandeps-perl \ libmodule-scandeps-perl \
libreadonly-perl \ libreadonly-perl \
libsys-meminfo-perl \ libregexp-common-perl \
libterm-readkey-perl \ libsys-meminfo-perl \
libtest-mockobject-perl \ libterm-readkey-perl \
libtest-pod-perl \ libtest-mockobject-perl \
libunicode-string-perl \ libtest-pod-perl \
liburi-perl \ libunicode-string-perl \
libwww-perl liburi-perl \
libwww-perl \
libtest-nowarnings-perl \
libtest-deep-perl \
libtest-warn-perl \
make \
cpanminus
After installing the dependencies, imapsync should be working, After installing the dependencies, imapsync should be working,
go to the section "After installing the dependencies" below. go to the section "After installing the dependencies" below.
@ -62,32 +73,48 @@ Here are the commands to install imapsync dependencies.
You need root priviledge to run them. You need root priviledge to run them.
The first command installs standard Debian packages: The first command installs standard Debian packages:
apt install \ apt install \
libauthen-ntlm-perl \ libauthen-ntlm-perl \
libcgi-pm-perl \ libcgi-pm-perl \
libcrypt-openssl-rsa-perl \ libcrypt-openssl-rsa-perl \
libdata-uniqid-perl \ libdata-uniqid-perl \
libfile-copy-recursive-perl \ libfile-copy-recursive-perl \
libio-socket-inet6-perl \ libio-socket-inet6-perl \
libio-socket-ssl-perl \ libio-socket-ssl-perl \
libio-tee-perl \ libio-tee-perl \
libhtml-parser-perl \ libhtml-parser-perl \
libmail-imapclient-perl \ libmail-imapclient-perl \
libparse-recdescent-perl \ libparse-recdescent-perl \
libmodule-scandeps-perl \ libmodule-scandeps-perl \
libreadonly-perl \ libreadonly-perl \
libterm-readkey-perl \ libterm-readkey-perl \
libtest-mockobject-perl \ libtest-mockobject-perl \
libtest-pod-perl \ libtest-pod-perl \
libunicode-string-perl \ libunicode-string-perl \
liburi-perl \ liburi-perl \
libwww-perl \ libwww-perl \
make \ libregexp-common-perl \
cpanminus libtest-nowarnings-perl \
libtest-deep-perl \
libtest-warn-perl \
make \
cpanminus
The package libdata-uniqid-perl is in the jessie-backports repository
https://packages.debian.org/fr/jessie-backports/libdata-uniqid-perl
Here is how to add jessie-backports repository in /etc/apt/sources.list
https://backports.debian.org/Instructions/
If you can't add the jessie-backports repository in /etc/apt/sources.list you
have to install Perl module Data::Uniqid with cpanm:
cpanm Data::Uniqid
The following second command installs "manually" the Perl module Sys::MemInfo The following second command installs "manually" the Perl module Sys::MemInfo
because Debian hasn't made it available via a package yet. because Debian 8 Jessie doesn't have this Perl module available via a package
(but Debian 9 Stretch does):
cpanm Sys::MemInfo cpanm Sys::MemInfo
@ -176,9 +203,7 @@ After installing the dependencies, imapsync should be working.
You don't have to be root to test and use imapsync. You don't have to be root to test and use imapsync.
Take imapsync either on github or at the upstream site: Take imapsync either on github or at the upstream site.
wget -N https://imapsync.lamiral.info/dist/imapsync
Add execution permission to the downloaded script: Add execution permission to the downloaded script:

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.Docker.txt,v 1.1 2017/09/03 03:23:54 gilles Exp gilles $ # $Id: INSTALL.Docker.txt,v 1.2 2017/10/22 14:21:46 gilles Exp gilles $
======================================= =======================================
= Installing imapsync docker image = Installing imapsync docker image
@ -14,4 +14,8 @@
docker run gilleslamiral/imapsync imapsync <usual imapsync arguments> docker run gilleslamiral/imapsync imapsync <usual imapsync arguments>
== Docker hub location ==
https://hub.docker.com/r/gilleslamiral/imapsync/

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.Docker_build.txt,v 1.5 2017/04/07 08:45:20 gilles Exp gilles $ # $Id: INSTALL.Docker_build.txt,v 1.7 2018/04/10 00:16:18 gilles Exp gilles $
================================================= =================================================
= Building an imapsync docker image from Debian = = Building an imapsync docker image from Debian =
@ -10,7 +10,7 @@
FROM debian:stretch FROM debian:stretch
LABEL maintainer "gilles.lamiral@laposte.net" LABEL maintainer "gilles@lamiral.info"
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y \ && apt-get install -y \
@ -29,6 +29,7 @@ RUN apt-get update \
libmodule-scandeps-perl \ libmodule-scandeps-perl \
libpar-packer-perl \ libpar-packer-perl \
libreadonly-perl \ libreadonly-perl \
libregexp-common-perl \
libsys-meminfo-perl \ libsys-meminfo-perl \
libterm-readkey-perl \ libterm-readkey-perl \
libtest-mockobject-perl \ libtest-mockobject-perl \

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.FreeBSD.txt,v 1.7 2016/11/07 10:40:53 gilles Exp gilles $ # $Id: INSTALL.FreeBSD.txt,v 1.8 2018/04/10 00:16:52 gilles Exp gilles $
================================== ==================================
= Installing imapsync on FreeBSD = = Installing imapsync on FreeBSD =

View File

@ -1,21 +1,46 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.OnlineUI.txt,v 1.8 2017/09/01 22:50:06 gilles Exp gilles $ # $Id: INSTALL.OnlineUI.txt,v 1.14 2018/04/24 00:14:51 gilles Exp gilles $
============================== ==============================
= Installing imapsync online = = Installing imapsync online =
============================== ==============================
Please consider this as relatively new and experimental. Please consider this as relatively new and experimental.
I add I'm begining to be confident with /X since the /X service I add I'm beginning to be confident with /X since the /X service
is up and running quite well since january 2017. is up and running quite well since January 2017.
You have to be a little familiar with what is a CGI script You have to be a little familiar with what a CGI script is
and how to activate it on an Apache (or any other) HTTP server. and how to activate a CGI script on an the Apache (or any other)
HTTP server.
The web visual user interface frontend is the file The web visual user interface frontend is compounded in three
https://imapsync.lamiral.info/X/imapsync_form.html files, a html5 file, a css file, and a javascript file:
You can do a "view source" to see it as it is written,
and a "save" to get it locally. * https://imapsync.lamiral.info/X/imapsync_form.html
* https://imapsync.lamiral.info/X/imapsync_form.js
* https://imapsync.lamiral.info/X/imapsync_form.css
You can do a "view source" to see the html file as
it is written, and a "save" to get it locally.
The two other files called imapsync_form.js and
imapsync_form.css can be saved the same way.
Those three files can be put anywhere on a web server,
as long as they stand in the same directory. If you
want to put them in different directories, just change
the content of imapsync_form.html to reflect the change,
ie, change the two lines referencing imapsync_form.css and imapsync_form.js
href="imapsync_form.css" (near the beginning of imapsync_form.html)
src="imapsync_form.js" (near the end of imapsync_form.html)
The actual imap syncing work is done by imapsync acting as a CGI,
the visual interface is only there to give imapsync the parameters
needed for the sync.
In order to make imapsync work as a cgi, there is two conditions.
First it has to work by itself on the web host. If imapsync
doesn't work by itself, on a command line, then it won't
work as a cgi.
This imapsync_form.html file in action calls the CGI location This imapsync_form.html file in action calls the CGI location
/cgi-bin/imapsync /cgi-bin/imapsync
@ -26,33 +51,42 @@ https://imapsync.lamiral.info/imapsync
It is the program file used verbatim for the service given at It is the program file used verbatim for the service given at
https://imapsync.lamiral.info/X/ https://imapsync.lamiral.info/X/
So copy both imapsync_form.html and imapsync on a HTTP server Copy imapsync_form.* on a directory that is visible by your HTTP server.
allowing CGIs and you'll have your own imapsync visual interface. Copy the imapsync script on the cgi-bin/ directory
allowing CGIs and you'll have your own imapsync visual interface
and service.
I haven't tested yet this visual interface on Windows nor Mac,
feedback is welcome from successes or failures on those platforms.
Example on a Debian server with Apache: Example on a Debian server with Apache:
Imapsync place on the server disk: Imapsync script place on the server disk:
/usr/lib/cgi-bin/imapsync /usr/lib/cgi-bin/imapsync
This classical /cgi-bin directory is configured in Apache This classical /cgi-bin directory is already configured
configuration file in the Apache configuration file
/etc/apache2/sites-available/default-ssl /etc/apache2/sites-available/default-ssl
or or
/etc/apache2/sites-available/default /etc/apache2/sites-available/default
It contains somewhere (maybe in comments for now, The configuration file contains somewhere,
with some # characters to make them ignored): maybe in comments for now, with some # characters
at the beginning to make them ignored:
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin"> <Directory "/usr/lib/cgi-bin">
AllowOverride None AllowOverride None
# Next line "no-gzip 1" is to avoid output buffering,
# clients can then see the log along the sync
SetEnv no-gzip 1
Options +ExecCGI -MultiViews Options +ExecCGI -MultiViews
Order allow,deny Order allow,deny
Allow from all Allow from all
</Directory> </Directory>
The UI frontend file place on the server disk is The UI front-end file place on the server disk is
/var/www/X/imapsync_form.html /var/www/X/imapsync_form.html
but it can be placed it anywhere on disk, the important but it can be placed it anywhere on disk, the important
thing is that it has to be served by the web server. thing is that it has to be served by the web server.
@ -60,11 +94,77 @@ thing is that it has to be served by the web server.
The imapsync working directory in cgi mode is The imapsync working directory in cgi mode is
/var/tmp/imapsync_cgi/ /var/tmp/imapsync_cgi/
it is not configurable unless changing it in it is not configurable unless changing it in
imapsync directly, it is hardcoded in imapsync. imapsync directly, it is hard-coded in imapsync.
In this directory will go the log files and In this directory will go the log files and
the pid files. the pid files.
Use at least CGI.pm release 4.08 (2014-10-18) Use at least CGI.pm release 4.08 (2014-10-18)
to avoid the bug "Undefined subroutine CGI::multi_param" to avoid the bug "Undefined subroutine CGI::multi_param"
You can use the command cpanm to upgrade CGI.pm to its last version,
it's the easiest way.
Example on a Centos 7 server with httpd Apache:
mkdir /var/www/html/X/
cp imapsync_form.html imapsync_form.js imapsync_form.css /var/www/html/X/
cp imapsync /var/www/cgi-bin/
Check
http://yourhost/X/imapsync_form.html
or the safer
https://yourhost/X/imapsync_form.html
That's all for installing a /X service on Centos 7.
====== mod_perl ======
The script imapsync doesn't work under Modperl::Registry
nor under ModPerl::PerlRun so read on if you think you
are better than me.
I've try the standard way, telling how any cgi perl script
can be run under mod_perl perlrun, but it fails with imapsync.
Any hint welcome!
# This is a Debian example
# install mod-perl with
apt-get install libapache2-mod-perl2
# edit the file /etc/apache2/mods-available/perl.conf
# with the following lines
more /etc/apache2/mods-available/perl.conf
<IfModule mod_perl.c>
PerlModule ModPerl::PerlRun
Alias /perl-run/ /usr/lib/cgi-bin/
<Location /perl-run>
SetHandler perl-script
PerlResponseHandler ModPerl::PerlRun
PerlOptions +ParseHeaders
Options +ExecCGI
</Location>
</IfModule>
# Enable the Apache perl module
a2enmod perl
# Verify perl.conf and perl.load are in directory mods-enabled/
ls mods-enabled/perl.*
# Reload Apache
apachectl graceful
# Verify imapsync works under perl-run
curl http://localhost/perl-run/imapsync
======================

View File

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: INSTALL.Ubuntu.txt,v 1.10 2017/03/30 11:23:37 gilles Exp gilles $ # $Id: INSTALL.Ubuntu.txt,v 1.12 2018/05/06 15:03:29 gilles Exp gilles $
================================================= =================================================
= Installing imapsync on Ubuntu 16.04 or higher = = Installing imapsync on Ubuntu 16.04 or higher =
@ -27,6 +27,7 @@ libmodule-scandeps-perl \
libnet-ssleay-perl \ libnet-ssleay-perl \
libpar-packer-perl \ libpar-packer-perl \
libreadonly-perl \ libreadonly-perl \
libregexp-common-perl \
libsys-meminfo-perl \ libsys-meminfo-perl \
libterm-readkey-perl \ libterm-readkey-perl \
libtest-fatal-perl \ libtest-fatal-perl \
@ -36,6 +37,9 @@ libtest-requires-perl \
libtest-simple-perl \ libtest-simple-perl \
libunicode-string-perl \ libunicode-string-perl \
liburi-perl \ liburi-perl \
libtest-nowarnings-perl \
libtest-deep-perl \
libtest-warn-perl \
make \ make \
cpanminus cpanminus

View File

@ -1,10 +1,11 @@
#!/bin/sh #!/bin/sh
# $Id: prerequisites_imapsync,v 1.21 2017/08/31 02:12:36 gilles Exp gilles $ # $Id: prerequisites_imapsync,v 1.25 2018/04/24 00:14:23 gilles Exp gilles $
MODULES_MANDATORY=' MODULES_MANDATORY='
App::cpanminus
Authen::NTLM Authen::NTLM
Class::Load CGI
Compress::Zlib Compress::Zlib
Crypt::OpenSSL::RSA Crypt::OpenSSL::RSA
Data::Dumper Data::Dumper
@ -28,7 +29,6 @@ Mail::IMAPClient
Module::Implementation Module::Implementation
Module::Runtime Module::Runtime
Module::ScanDeps Module::ScanDeps
Net::Ping
Net::SSLeay Net::SSLeay
Package::Stash Package::Stash
Package::Stash::XS Package::Stash::XS
@ -36,6 +36,7 @@ PAR::Packer
Parse::RecDescent Parse::RecDescent
Pod::Usage Pod::Usage
Readonly Readonly
Regexp::Common
Sys::MemInfo Sys::MemInfo
Term::ReadKey Term::ReadKey
Test::Fatal Test::Fatal
@ -44,6 +45,9 @@ Test::MockObject
Test::More Test::More
Test::Pod Test::Pod
Test::Requires Test::Requires
Test::NoWarnings
Test::Deep
Test::Warn
Try::Tiny Try::Tiny
Unicode::String Unicode::String
URI::Escape URI::Escape
@ -187,4 +191,6 @@ EXIT=$?
# Help the user to install missing modules # Help the user to install missing modules
search_modules_any $LIST_TO_INSTALL search_modules_any $LIST_TO_INSTALL
test "$1" = "MODULES_MANDATORY" && search_modules_any $MODULES_MANDATORY
exit $EXIT exit $EXIT

View File

@ -0,0 +1,40 @@
Here is imapsync 1.882 on host petite, a linux system with 0.1/2.0 free GiB of RAM
with Perl 5.22.1 and Mail::IMAPClient 3.39
Transfer started at Sun May 6 01:19:07 2018
PID is 8751
Log file is LOG_imapsync/imapsync_abortme.log ( to change it, use --logfile path ; or use --nolog to turn off logging )
Load is 0.60 0.56 0.79 2/503 on 2 cores
Current directory is /home/gilles/public_html/imapsync
Real user id is gilles (uid 1000)
Effective user id is gilles (euid 1000)
$RCSfile: imapsync,v $ $Revision: 1.882 $ $Date: 2018/05/05 21:10:43 $
Command line used:
./imapsync --host1 localhost --user1 tata --passfile1 ../../var/pass/secret.tata --host2 localhost --user2 titi --passfile2 ../../var/pass/secret.titi --pidfile /tmp/imapsync_abortme.pid --logfile imapsync_abortme.log --simulong 4
Temp directory is /tmp ( to change it use --tmpdir dirpath )
kill -QUIT 8751 # special behavior
kill -TERM 8751 # special behavior
kill -INT 8751 # special behavior
kill -USR1 8751 # special behavior
PID file is /tmp/imapsync_abortme.pid ( to change it use --pidfile filepath ; to avoid it use --pidfile "" )
Writing my PID 8751 in /tmp/imapsync_abortme.pid
Are you still here 1/20
Are you still here 2/20
Are you still here 3/20
Are you still here 4/20
Are you still here 5/20
Are you still here 6/20
Are you still here 7/20
Are you still here 8/20
Are you still here 9/20
Are you still here 10/20
Are you still here 11/20
Are you still here 12/20
Are you still here 13/20
Got a signal QUIT (my PID is 8751). Asked to terminate
Here are the final stats of this sync not completely finished so far
Ended by a signal QUIT (my PID is 8751). I am asked to terminate immediately.
You should resynchronize those accounts by running a sync again,
since some messages and entire folders might still be missing on host2.
Exiting with return value 6
Log file is LOG_imapsync/imapsync_abortme.log ( to change it, use --logfile filepath ; or use --nolog to turn off logging )

227
Makefile
View File

@ -1,29 +1,29 @@
# $Id: Makefile,v 1.257 2017/09/11 11:11:18 gilles Exp gilles $ # $Id: Makefile,v 1.269 2018/05/06 15:09:09 gilles Exp gilles $
.PHONY: help usage all doc .PHONY: help usage all doc
help: usage help: usage
usage: usage:
@echo " imapsync $(VERSION), You can do :" @echo " this is imapsync $(VERSION), You can do :"
@echo "make testp # it shows needed Perl modules from your distro or CPAN" @echo "make testp # it shows needed Perl modules from your distro or CPAN"
@echo "make install # as root" @echo "make install # as root"
@echo "" @echo ""
@echo "All other goals are for the upstream developper" @echo "All other goals are for the upstream developper"
@echo "make testf # run tests" @echo "make testf # run tests"
@echo "make testv # run tests verbosely" @echo "make testv # run tests verbosely"
@echo "make test_quick # few tests verbosely" @echo "make test_quick # few tests verbosely"
@echo "make W/test.bat # run --tests and W/test.bat on win32" @echo "make W/test.bat # run --tests and W/test.bat on win32"
@echo "make W/test_tests.bat # run --tests on win32" @echo "make W/test_tests.bat # run --tests on win32"
@echo "make W/test_testsdebug.bat # run --testsdebug on win32" @echo "make W/test_testsdebug.bat # run --testsdebug on win32"
@echo "make W/test2.bat # run W/test2.bat on win32" @echo "make W/test2.bat # run W/test2.bat on win32"
@echo "make W/test3.bat # run W/test3.bat on win32" @echo "make W/test3.bat # run W/test3.bat on win32"
@echo "make W/test_reg.bat # run W/test_reg.bat on win32" @echo "make W/test_reg.bat # run W/test_reg.bat on win32"
@echo "make W/test_exe.bat # run W/test_exe.bat on win32" @echo "make W/test_exe.bat # run W/test_exe.bat on win32"
@echo "make W/test_exe_tests.bat # run W/test_exe_tests.bat on win32" @echo "make W/test_exe_tests.bat # run W/test_exe_tests.bat on win32"
@echo "make W/test_exe_2.bat # run W/test_exe_2.bat on win32" @echo "make W/test_exe_2.bat # run W/test_exe_2.bat on win32"
@echo "make examples/sync_loop_windows.bat # run examples/sync_loop_windows.bat on win32" @echo "make examples/sync_loop_windows.bat # run examples/sync_loop_windows.bat on win32"
@echo "make win32_prereq # run W/install_modules.bat on win32" @echo "make win32_prereq # run W/install_modules.bat on win32"
@ -34,7 +34,7 @@ usage:
@echo "make upload_FAQ # upload FAQs and documentation" @echo "make upload_FAQ # upload FAQs and documentation"
@echo "make upload_X # upload online UI" @echo "make upload_X # upload online UI"
@echo "make upload_latest # upload latest imapsync and binaries (dev)" @echo "make upload_latest # upload latest imapsync and binaries (dev)"
@echo "make upload_cgi # upload latest imapsync" @echo "make upload_cgi # upload latest imapsync online, after local and remote --tests success."
@echo "make valid_index # check index.shtml for good syntax" @echo "make valid_index # check index.shtml for good syntax"
@echo "make upload_ks" @echo "make upload_ks"
@echo "make imapsync.exe" @echo "make imapsync.exe"
@ -49,34 +49,42 @@ usage:
@echo "make cle # Check links of S/*.shtml" @echo "make cle # Check links of S/*.shtml"
@echo "make mactestsdebug # run ./imapsync --testsdebug on Mac" @echo "make mactestsdebug # run ./imapsync --testsdebug on Mac"
@echo "make mactests # run ./imapsync --tests on Mac" @echo "make mactests # run ./imapsync --tests on Mac"
@echo "make mactestslive # run ./imapsync --testslive on Mac"
@echo "make ks2testsdebug # run ./imapsync --testsdebug on ks2" @echo "make ks2testsdebug # run ./imapsync --testsdebug on ks2"
@echo "make ks2tests # run ./imapsync --tests on ks2" @echo "make ks2tests # run ./imapsync --tests on ks2"
@echo "make ks2testslive # run ./imapsync --testslive on ks2"
PREFIX ?= /usr PREFIX ?= /usr
DIST_NAME=imapsync-$(VERSION) DIST_PATH ::= dist2/
DIST_FILE=$(DIST_NAME).tgz VERSION ::= $(shell perl ./imapsync --version 2>/dev/null || cat VERSION)
DEB_FILE=$(DIST_NAME).deb VERSION_PREVIOUS ::= $(shell perl ./$(DIST_PATH)/imapsync --version 2>/dev/null || echo ERROR)
VERSION_EXE ::= $(shell cat ./VERSION_EXE)
VERSION=$(shell perl -I$(IMAPClient) ./imapsync --version 2>/dev/null || cat VERSION) IMAPClient_3xx ::= ./W/Mail-IMAPClient-3.39/lib
VERSION_PREVIOUS=$(shell perl -I$(IMAPClient) ./dist/imapsync --version 2>/dev/null || echo ERROR) IMAPClient ::= $(IMAPClient_3xx)
VERSION_EXE=$(shell cat ./VERSION_EXE)
HELLO=$(shell date;uname -a)
IMAPClient_3xx=./W/Mail-IMAPClient-3.39/lib
IMAPClient=$(IMAPClient_3xx)
HOSTNAME = $(shell hostname -s) DIST_NAME ::= imapsync-$(VERSION)
ARCH = $(shell uname -m) DIST_FILE ::= $(DIST_NAME).tgz
KERNEL = $(shell uname -s) DEB_FILE ::= $(DIST_NAME).deb
BIN_NAME = imapsync_bin_$(KERNEL)_$(ARCH)
DISTRO_NAME = $(shell lsb_release -i -s || echo Unknown) HELLO ::= $(shell date;uname -a)
DISTRO_RELEASE = $(shell lsb_release -r -s || echo 0.0)
DISTRO_CODE = $(shell lsb_release -c -s || echo Unknown) HOSTNAME ::= $(shell hostname -s)
DISTRO = $(DISTRO_NAME)_$(DISTRO_RELEASE)_$(DISTRO_CODE) ARCH ::= $(shell uname -m)
KERNEL ::= $(shell uname -s)
BIN_NAME ::= imapsync_bin_$(KERNEL)_$(ARCH)
DISTRO_NAME ::= $(shell lsb_release -i -s || echo Unknown)
DISTRO_RELEASE ::= $(shell lsb_release -r -s || echo 0.0)
DISTRO_CODE ::= $(shell lsb_release -c -s || echo Unknown)
DISTRO ::= $(DISTRO_NAME)_$(DISTRO_RELEASE)_$(DISTRO_CODE)
hello: hello:
@echo "$(VERSION)" @echo "$(VERSION)"
@echo "$(DIST_NAME)"
@echo "$(VERSION_PREVIOUS)"
@echo "$(VERSION_EXE)"
@echo "$(IMAPClient)" @echo "$(IMAPClient)"
@echo "$(HOSTNAME)" @echo "$(HOSTNAME)"
@echo "$(ARCH)" @echo "$(ARCH)"
@ -128,10 +136,11 @@ clean: clean_tilde clean_man clean_log clean_bak clean_permissions
clean_permissions: clean_permissions:
chmod a-x Makefile FAQ.d/FAQ.*.txt README_Windows.txt chmod a-x Makefile FAQ.d/FAQ.*.txt README_Windows.txt
chmod a-x FAQ.d/RCS/FAQ.*.txt,v
chmod a-x INSTALL.d/INSTALL.*.txt chmod a-x INSTALL.d/INSTALL.*.txt
chmod a-x X/progress.html X/imapsync_form.html chmod a-x X/progress.html X/imapsync_form.html
chmod a-x S/*.shtml S/*.html chmod a-x S/*.shtml S/*.html index.shtml S/RCS/*.shtml,v S/RCS/*.html,v
chmod a-x doc/*.t2t dist/*.txt chmod a-x doc/*.t2t $(DIST_PATH)/*.txt
clean_test: clean_test:
rm -f .test_3xx rm -f .test_3xx
@ -166,71 +175,70 @@ install: testp W/imapsync.1
.PHONY: cidone ci
ci: cidone
cidone:
rcsdiff W/*.bat W/*.sh W/*.out W/*.txt W/*.htaccess
rcsdiff doc/*.t2t
rcsdiff INSTALL.d/*.txt INSTALL.d/prerequisites_imapsync
rcsdiff FAQ.d/*.txt
rcsdiff examples/*.sh examples/*.bat examples/*.txt
rcsdiff RCS/*
rcsdiff W/tools/backup_old_dist W/tools/gen_README_dist W/tools/validate_html4 W/tools/validate_xml_html5 W/tools/fix_email_for_exchange.py
rcsdiff S/*.txt S/*.shtml S/*.html
############### ###############
# Local goals # Local goals
############### ###############
.PHONY: prereq test tests unitests testp testf test3xx testv3 perlcritic allcritic crit compok dev .PHONY: prereq test tests unitests testp testf test3xx testv3 perlcritic allcritic crit compok dev cover tidy
dev: test crit bin dev: test crit bin
docker: docker:
ssh ks3 'cd docker/imapsync && . memo' ssh ks3 'cd docker/imapsync && . memo'
cover:
perl -MDevel::Cover ./imapsync --tests
tidy: W/imapsync.tdy
W/imapsync.tdy: imapsync
perltidy -i=8 -sts -pt=0 -l=0 -o W/imapsync.tdy imapsync
compok: W/.compok compok: W/.compok
W/.compok: imapsync W/.compok: imapsync
perl -c imapsync perl -c imapsync
touch W/.compok date >> W/.compok
prereq: W/prereq.scandeps.$(DISTRO).txt prereq: W/prereq.scandeps.$(DISTRO).txt W/prereq.$(DISTRO).txt
W/prereq.scandeps.$(DISTRO).txt: INSTALL.d/prerequisites_imapsync imapsync W/prereq.scandeps.$(DISTRO).txt: INSTALL.d/prerequisites_imapsync imapsync
scandeps -c -x imapsync | tee W/prereq.scandeps.$(DISTRO).txt scandeps -c -x imapsync | tee W/prereq.scandeps.$(DISTRO).txt
rcsdiff W/prereq.scandeps.$(DISTRO).txt || { echo 'rcsdiff detected a diff' | ci -l W/prereq.scandeps.$(DISTRO).txt ; } rcsdiff W/prereq.scandeps.$(DISTRO).txt || { echo 'rcsdiff detected a diff' | ci -l W/prereq.scandeps.$(DISTRO).txt ; }
W/prereq.$(DISTRO).txt: INSTALL.d/prerequisites_imapsync imapsync
./INSTALL.d/prerequisites_imapsync | tee W/prereq.$(DISTRO).txt ./INSTALL.d/prerequisites_imapsync | tee W/prereq.$(DISTRO).txt
rcsdiff W/prereq.$(DISTRO).txt || { echo 'rcsdiff detected a diff' | ci -l W/prereq.$(DISTRO).txt ; }
crit: allcritic crit: allcritic
perlcritic: W/perlcritic_3.out W/perlcritic_2.out perlcritic: W/perlcritic_3.txt W/perlcritic_2.txt
allcritic: W/perlcritic_4.out W/perlcritic_3.out W/perlcritic_2.out W/perlcritic_1.out allcritic: W/perlcritic_4.txt W/perlcritic_3.txt W/perlcritic_2.txt W/perlcritic_1.txt
W/perlcritic_1.out: imapsync W/.compok W/perlcritic_1.txt: imapsync W/.compok
perlcritic --statistics -1 imapsync > W/perlcritic_1.out.tmp || : perlcritic --statistics -1 imapsync > W/perlcritic_1.txt.tmp || :
mv W/perlcritic_1.out.tmp W/perlcritic_1.out mv W/perlcritic_1.txt.tmp W/perlcritic_1.txt
echo | ci -l W/perlcritic_1.out echo | ci -l W/perlcritic_1.txt
W/perlcritic_2.out: imapsync W/.compok W/perlcritic_2.txt: imapsync W/.compok
perlcritic --statistics -2 imapsync > W/perlcritic_2.out.tmp || : perlcritic --statistics -2 imapsync > W/perlcritic_2.txt.tmp || :
mv W/perlcritic_2.out.tmp W/perlcritic_2.out mv W/perlcritic_2.txt.tmp W/perlcritic_2.txt
echo | ci -l W/perlcritic_2.out echo | ci -l W/perlcritic_2.txt
W/perlcritic_3.out: imapsync W/.compok W/perlcritic_3.txt: imapsync W/.compok
perlcritic --statistics -3 imapsync > W/perlcritic_3.out.tmp || : perlcritic --statistics -3 imapsync > W/perlcritic_3.txt.tmp || :
mv W/perlcritic_3.out.tmp W/perlcritic_3.out mv W/perlcritic_3.txt.tmp W/perlcritic_3.txt
echo | ci -l W/perlcritic_3.out echo | ci -l W/perlcritic_3.txt
W/perlcritic_4.out: imapsync W/.compok W/perlcritic_4.txt: imapsync W/.compok
perlcritic --statistics -4 imapsync > W/perlcritic_4.out.tmp || : perlcritic --statistics -4 imapsync > W/perlcritic_4.txt.tmp || :
mv W/perlcritic_4.out.tmp W/perlcritic_4.out mv W/perlcritic_4.txt.tmp W/perlcritic_4.txt
echo | ci -l W/perlcritic_4.out echo | ci -l W/perlcritic_4.txt
test_quick : test_quick_3xx test_quick : test_quick_3xx
@ -297,7 +305,12 @@ examples/sync_loop_windows.bat:
unix2dos examples/sync_loop_windows.bat unix2dos examples/sync_loop_windows.bat
scp imapsync examples/file.txt examples/sync_loop_windows.bat Admin@c:'C:/msys/1.0/home/Admin/imapsync/' scp imapsync examples/file.txt examples/sync_loop_windows.bat Admin@c:'C:/msys/1.0/home/Admin/imapsync/'
ssh Admin@c 'C:/msys/1.0/home/Admin/imapsync/sync_loop_windows.bat --nodry --dry --nodry' ssh Admin@c 'C:/msys/1.0/home/Admin/imapsync/sync_loop_windows.bat --nodry --dry --nodry'
# ssh Admin@c 'C:/msys/1.0/home/Admin/imapsync/sync_loop_windows.bat '
examples/infinite_loop_windows.bat:
unix2dos examples/infinite_loop_windows.bat
scp examples/infinite_loop_windows.bat Admin@c:'C:/msys/1.0/home/Admin/imapsync/'
ssh Admin@c 'C:/msys/1.0/home/Admin/imapsync/infinite_loop_windows.bat'
W/test2.bat: W/test2.bat:
unix2dos W/test2.bat unix2dos W/test2.bat
@ -442,6 +455,11 @@ mactestsdebug:
rsync -p -e 'ssh -p 995' imapsync gilleslamira@gate.polarhome.com: rsync -p -e 'ssh -p 995' imapsync gilleslamira@gate.polarhome.com:
ssh -p 995 gilleslamira@gate.polarhome.com '. .bash_profile; perl imapsync --testsdebug --debug' ssh -p 995 gilleslamira@gate.polarhome.com '. .bash_profile; perl imapsync --testsdebug --debug'
mactestslive:
rsync -p -e 'ssh -p 995' imapsync gilleslamira@gate.polarhome.com:
ssh -p 995 gilleslamira@gate.polarhome.com '. .bash_profile; perl imapsync --testslive'
bin: lin mac win bin: lin mac win
lin: $(BIN_NAME) lin: $(BIN_NAME)
@ -468,24 +486,32 @@ $(BIN_NAME): imapsync
lfo: upload_lfo lfo: upload_lfo
.PHONY: tarball .PHONY: tarball cidone ci
tarball: tarball: cidone
echo making tarball ../prepa_dist/$(DIST_FILE) echo making tarball ../prepa_dist/$(DIST_FILE)
rcsdiff RCS/*
cd W && rcsdiff RCS/*
cd examples && rcsdiff RCS/*
mkdir -p dist mkdir -p dist
mkdir -p ../prepa_dist/$(DIST_NAME) mkdir -p ../prepa_dist/$(DIST_NAME)
rsync -aCvH --delete --omit-dir-times --exclude dist/ --exclude imapsync.exe ./ ../prepa_dist/$(DIST_NAME)/ rsync -aCvH --delete --omit-dir-times --exclude $(DIST_PATH) --exclude imapsync.exe ./ ../prepa_dist/$(DIST_NAME)/
cd ../prepa_dist && tar czfv $(DIST_FILE) $(DIST_NAME) cd ../prepa_dist && tar czfv $(DIST_FILE) $(DIST_NAME)
cd ../prepa_dist && md5sum $(DIST_FILE) > $(DIST_FILE).md5.txt cd ../prepa_dist && md5sum $(DIST_FILE) > $(DIST_FILE).md5.txt
cd ../prepa_dist && md5sum -c $(DIST_FILE).md5.txt cd ../prepa_dist && md5sum -c $(DIST_FILE).md5.txt
ls -l ../prepa_dist/$(DIST_FILE) ls -l ../prepa_dist/$(DIST_FILE)
ci: cidone
cidone:
rcsdiff RCS/*
rcsdiff W/*.bat W/*.sh W/*.txt W/*.txt W/*.htaccess
cd W && rcsdiff RCS/*
rcsdiff doc/*.t2t
rcsdiff INSTALL.d/*.txt INSTALL.d/prerequisites_imapsync
rcsdiff FAQ.d/*.txt
rcsdiff examples/*.sh examples/*.bat examples/*.txt
cd examples && rcsdiff RCS/*
rcsdiff W/tools/backup_old_dist W/tools/gen_README_dist W/tools/validate_html4 W/tools/validate_xml_html5 W/tools/fix_email_for_exchange.py
rcsdiff S/*.txt S/*.shtml S/*.html
DIST_PATH := ./dist/
dist: cidone test clean all perlcritic dist_prepa dist_zip README_dist dist: cidone test clean all perlcritic dist_prepa dist_zip README_dist
@ -499,7 +525,7 @@ sha:
.PHONY: moveoldrelease ks2testsdebug ks2tests README_dist .PHONY: moveoldrelease ks2testsdebug ks2tests README_dist
moveoldrelease: moveoldrelease:
./W/tools/backup_old_dist ./W/tools/backup_old_dist $(DIST_PATH)
dist_prepa: tarball moveoldrelease dist_prepa: tarball moveoldrelease
@ -519,7 +545,7 @@ README_dist:
sh W/tools/gen_README_dist > $(DIST_PATH)/README.txt sh W/tools/gen_README_dist > $(DIST_PATH)/README.txt
unix2dos $(DIST_PATH)/README.txt unix2dos $(DIST_PATH)/README.txt
.PHONY: publish upload_ks ks valid_index biz .PHONY: publish upload_ks ks valid_index biz ks2tests ks2tests_gilles ks2tests_root
biz: S/imapsync_sold_by_country.txt biz: S/imapsync_sold_by_country.txt
@ -530,10 +556,12 @@ S/imapsync_sold_by_country.txt: imapsync
ks: ks:
rsync -avHz --delete --exclude imapsync.exe \ rsync -avHz --delete --exclude imapsync.exe \
. gilles@ks.lamiral.info:public_html/imapsync/ . gilles@ks.lamiral.info:public_html/imapsync/
ssh root@ks.lamiral.info 'apachectl configtest && /etc/init.d/apache2 reload'
ksa: ksa:
rsync -avHz --delete -P \ rsync -avHz --delete -P \
. gilles@ks.lamiral.info:public_html/imapsync/ . gilles@ks.lamiral.info:public_html/imapsync/
ssh root@ks.lamiral.info 'apachectl configtest && /etc/init.d/apache2 reload'
ks3: ks3:
rsync -avHz --delete -P \ rsync -avHz --delete -P \
@ -549,13 +577,34 @@ ks2testsdebug:
rsync -aP imapsync gilles@ks.lamiral.info:public_html/imapsync/imapsync rsync -aP imapsync gilles@ks.lamiral.info:public_html/imapsync/imapsync
ssh gilles@ks.lamiral.info 'public_html/imapsync/imapsync --testsdebug' ssh gilles@ks.lamiral.info 'public_html/imapsync/imapsync --testsdebug'
ks2tests: ks2tests: ks2tests_gilles ks2tests_root
ks2tests_gilles:
rsync -aP imapsync gilles@ks.lamiral.info:public_html/imapsync/imapsync rsync -aP imapsync gilles@ks.lamiral.info:public_html/imapsync/imapsync
ssh gilles@ks.lamiral.info 'public_html/imapsync/imapsync --tests' ssh gilles@ks.lamiral.info 'public_html/imapsync/imapsync --tests'
ks2tests_root:
rsync -aP imapsync root@ks.lamiral.info:
ssh root@ks.lamiral.info './imapsync --tests'
ks2testslive:
rsync -aP imapsync gilles@ks.lamiral.info:public_html/imapsync/imapsync
ssh gilles@ks.lamiral.info 'public_html/imapsync/imapsync --testslive'
publish: dist upload_ks ksa publish: dist upload_ks ksa
echo Now ou can do make ml echo Now ou can do make ml
centos:
scp imapsync INSTALL.d/prerequisites_imapsync root@vp1:
ssh root@vp1 sh prerequisites_imapsync
PUBLIC = ./ChangeLog ./NOLIMIT ./LICENSE ./CREDITS ./FAQ \ PUBLIC = ./ChangeLog ./NOLIMIT ./LICENSE ./CREDITS ./FAQ \
./index.shtml ./INSTALL ./README_Windows.txt \ ./index.shtml ./INSTALL ./README_Windows.txt \
./VERSION ./VERSION_EXE ./imapsync \ ./VERSION ./VERSION_EXE ./imapsync \
@ -598,8 +647,8 @@ cle: ./W/checklinkext.txt
http://lamiral.info/~gilles/imapsync/S/imapservers.shtml \ http://lamiral.info/~gilles/imapsync/S/imapservers.shtml \
| tee ./W/checklinkext.txt | tee ./W/checklinkext.txt
W/.valid.index.shtml: index.shtml S/*.shtml W/.valid.index.shtml: index.shtml
for f in index.shtml S/*.shtml; do echo tidy -q $$f; tidy -q $$f > /dev/null; done for f in index.shtml S/*.shtml; do echo tidy -e -q $$f; tidy -e -q $$f ; done
./W/tools/validate_xml_html5 index.shtml S/*.shtml ./W/tools/validate_xml_html5 index.shtml S/*.shtml
touch W/.valid.index.shtml touch W/.valid.index.shtml
@ -609,9 +658,9 @@ upload_bin:
rsync -a imapsync.exe imapsync_bin_Darwin imapsync_bin_Linux_i686 imapsync ../imapsync_website/ rsync -a imapsync.exe imapsync_bin_Darwin imapsync_bin_Linux_i686 imapsync ../imapsync_website/
rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/ rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/
upload_index: W/.valid.index.shtml upload_index: W/.valid.index.shtml clean_permissions
rcsdiff index.shtml S/style.css S/*.shtml FAQ.d/*.txt LICENSE CREDITS TODO examples/*.bat index.shtml INSTALL.d/*.txt rcsdiff index.shtml README_Windows.txt S/style.css S/*.shtml FAQ.d/*.txt LICENSE CREDITS TODO examples/*.bat index.shtml INSTALL.d/*.txt
rsync -avH index.shtml FAQ INSTALL NOLIMIT LICENSE CREDITS TODO S/robots.txt S/favicon.ico ../imapsync_website/ rsync -avH index.shtml README_Windows.txt FAQ INSTALL NOLIMIT LICENSE CREDITS TODO S/robots.txt S/favicon.ico ../imapsync_website/
rsync -aHv --delete ./W/ks.htaccess ../imapsync_website/.htaccess rsync -aHv --delete ./W/ks.htaccess ../imapsync_website/.htaccess
rsync -aHv --delete S/ ../imapsync_website/S/ rsync -aHv --delete S/ ../imapsync_website/S/
rsync -aHv --delete ./examples/ ../imapsync_website/examples/ rsync -aHv --delete ./examples/ ../imapsync_website/examples/
@ -625,17 +674,18 @@ ci_imapsync:
rcsdiff imapsync rcsdiff imapsync
upload_latest: unitests ci_imapsync bin upload_latest: unitests ci_imapsync bin
rsync -a imapsync imapsync_bin_Linux_i686 imapsync_bin_Darwin imapsync.exe ../imapsync_website/ rsync -a imapsync imapsync_bin_Linux_i686 imapsync_bin_Darwin imapsync.exe ./INSTALL.d/prerequisites_imapsync ../imapsync_website/
rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/ rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/
ssh root@ks.lamiral.info 'apachectl configtest && /etc/init.d/apache2 reload'
upload_cgi: unitests ks2tests ci_imapsync upload_cgi: unitests ks2tests ci_imapsync
rsync -a imapsync ../imapsync_website/ rsync -a imapsync ../imapsync_website/
rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/ rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/
upload_X: upload_X:
./W/tools/validate_xml_html5 X/imapsync_form.html ./W/tools/validate_xml_html5 X/imapsync_form.html
rcsdiff X/imapsync_form.html rcsdiff X/imapsync_form.html
rcsdiff X/imapsync_form.js
rsync -av --delete X/ ../imapsync_website/X/ rsync -av --delete X/ ../imapsync_website/X/
rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/ rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/
@ -652,9 +702,10 @@ upload_ks: ci tarball
rsync -aHv $(PUBLIC) ../imapsync_website/ rsync -aHv $(PUBLIC) ../imapsync_website/
rsync -aHv --delete ./W/ks.htaccess ../imapsync_website/.htaccess rsync -aHv --delete ./W/ks.htaccess ../imapsync_website/.htaccess
rsync -avH ./S/ ../imapsync_website/S/ rsync -avH ./S/ ../imapsync_website/S/
rsync -aHv --delete ./dist/ ../imapsync_website/dist/ rsync -aHv --delete ./$(DIST_PATH)/ ../imapsync_website/$(DIST_PATH)/
rsync -aHv --delete ./examples/ ../imapsync_website/examples/ rsync -aHv --delete ./examples/ ../imapsync_website/examples/
rsync -aHv --delete ./INSTALL.d/ ../imapsync_website/INSTALL.d/ rsync -aHv --delete ./INSTALL.d/ ../imapsync_website/INSTALL.d/
rsync -aHv --delete ./FAQ.d/ ../imapsync_website/FAQ.d/ rsync -aHv --delete ./FAQ.d/ ../imapsync_website/FAQ.d/
rsync -avH --delete ./doc/ ../imapsync_website/doc/ rsync -avH --delete ./doc/ ../imapsync_website/doc/
rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/ rsync -aHvz --delete ../imapsync_website/ root@ks.lamiral.info:/var/www/imapsync/
ssh root@ks.lamiral.info 'apachectl configtest && /etc/init.d/apache2 reload'

181
README
View File

@ -5,7 +5,7 @@ NAME
VERSION VERSION
This documentation refers to Imapsync $Revision: 1.4 $ This documentation refers to Imapsync $Revision: 1.882 $
USAGE USAGE
@ -21,7 +21,8 @@ USAGE
DESCRIPTION DESCRIPTION
We sometimes need to transfer mailboxes from one imap server to another. We sometimes need to transfer mailboxes from one imap server to one
another.
Imapsync command is a tool allowing incremental and recursive imap Imapsync command is a tool allowing incremental and recursive imap
transfers from one mailbox to another. transfers from one mailbox to another.
@ -31,28 +32,37 @@ DESCRIPTION
(\Seen \Answered \Flagged etc.) are synced too. (\Seen \Answered \Flagged etc.) are synced too.
Imapsync reduces the amount of data transferred by not transferring a Imapsync reduces the amount of data transferred by not transferring a
given message if it resides already on both sides. Same specific headers given message if it resides already on both sides.
and the transfer is done only once (by default it's "Message-Id:" and
"Received:" lines but it can be changed with --useheader option).
All flags are preserved, unread will stay unread, read will stay read, Same specific headers and the transfer is done only once. By default,
deleted will stay deleted. the identification headers are "Message-Id:" and "Received:" lines but
this choice can be changed with the --useheader option.
All flags are preserved, unread messages will stay unread, read ones
will stay read, deleted will stay deleted.
You can stop the transfer at any time and restart it later, imapsync You can stop the transfer at any time and restart it later, imapsync
works well with bad connections and interruptions. works well with bad connections and interruptions, by design.
You can decide to delete the messages from the source mailbox after a You can decide to delete the messages from the source mailbox after a
successful transfer, it can be a good feature when migrating live successful transfer, it can be a good feature when migrating live
mailboxes since messages will be only on one side. In that case, use the mailboxes since messages will be only on one side.
--delete1 option. Option --delete1 implies also option --expunge1 so all
messages marked deleted on host1 will be really deleted. In that case, use the --delete1 option. Option --delete1 implies also
option --expunge1 so all messages marked deleted on host1 will be really
deleted.
You can also decide to remove empty folders once all of their messages
have been transferred. Add --delete1emptyfolders to obtain this
behavior.
A different scenario is synchronizing a mailbox B from another mailbox A A different scenario is synchronizing a mailbox B from another mailbox A
in case you just want to keep a "live" copy of A in B. In that case in case you just want to keep a "live" copy of A in B.
--delete2 has to be used, it deletes messages in host2 folder B that are
not in host1 folder A. If you also need to destroy host2 folders that For this, option --delete2 has to be used, it deletes messages in host2
are not in host1 then use --delete2folders (see also folder B that are not in host1 folder A. If you also need to destroy
--delete2foldersonly and --delete2foldersbutnot). host2 folders that are not in host1 then use --delete2folders. See also
--delete2foldersonly and --delete2foldersbutnot.
Imapsync is not adequate for maintaining two active imap accounts in Imapsync is not adequate for maintaining two active imap accounts in
synchronization when the user plays independently on both sides. Use synchronization when the user plays independently on both sides. Use
@ -80,11 +90,14 @@ OPTIONS
OPTIONS/credentials OPTIONS/credentials
--host1 str : Source or "from" imap server. Mandatory. --host1 str : Source or "from" imap server. Mandatory.
--port1 int : Port to connect on host1. Default is 143, 993 if --ssl1 --port1 int : Port to connect on host1.
Optional since default port is 143 or 993 if --ssl1
--user1 str : User to login on host1. Mandatory. --user1 str : User to login on host1. Mandatory.
--password1 str : Password for the user1. --password1 str : Password for the user1.
--host2 str : "destination" imap server. Mandatory. --host2 str : "destination" imap server. Mandatory.
--port2 int : Port to connect on host2. Default is 143, 993 if --ssl2 --port2 int : Port to connect on host2.
Optional since default port is 143 or 993 if --ssl2
--user2 str : User to login on host2. Mandatory. --user2 str : User to login on host2. Mandatory.
--password2 str : Password for the user2. --password2 str : Password for the user2.
@ -101,13 +114,18 @@ OPTIONS
--nossl1 : Do not use a SSL connection on host1. --nossl1 : Do not use a SSL connection on host1.
--ssl1 : Use a SSL connection on host1. On by default if possible. --ssl1 : Use a SSL connection on host1. On by default if possible.
--nossl2 : Do not use a SSL connection on host2. --nossl2 : Do not use a SSL connection on host2.
--ssl2 : Use a SSL connection on host2. On by default if possible. --ssl2 : Use a SSL connection on host2. On by default if possible.
--notls1 : Do not use a TLS connection on host1. --notls1 : Do not use a TLS connection on host1.
--tls1 : Use a TLS connection on host1. On by default if possible. --tls1 : Use a TLS connection on host1. On by default if possible.
--notls2 : Do not use a TLS connection on host2. --notls2 : Do not use a TLS connection on host2.
--tls2 : Use a TLS connection on host2. On by default if possible. --tls2 : Use a TLS connection on host2. On by default if possible.
--debugssl int : SSL debug mode from 0 to 4. --debugssl int : SSL debug mode from 0 to 4.
--sslargs1 str : Pass any ssl parameter for host1 ssl or tls connection. Example: --sslargs1 str : Pass any ssl parameter for host1 ssl or tls connection. Example:
--sslargs1 SSL_verify_mode=1 --sslargs1 SSL_version=SSLv3 --sslargs1 SSL_verify_mode=1 --sslargs1 SSL_version=SSLv3
See all possibilities in the new() method of IO::Socket::SSL See all possibilities in the new() method of IO::Socket::SSL
@ -153,7 +171,8 @@ OPTIONS
--nomixfolders : Do not merge folders when host1 is case-sensitive --nomixfolders : Do not merge folders when host1 is case-sensitive
while host2 is not (like Exchange). Only the first while host2 is not (like Exchange). Only the first
similar folder is synced (ex: Sent SENT sent -> Sent). similar folder is synced (ex: with Sent SENT sent
on host1 only Sent will be synced to host2).
--skipemptyfolders : Empty host1 folders are not created on host2. --skipemptyfolders : Empty host1 folders are not created on host2.
@ -166,20 +185,17 @@ OPTIONS
--exclude 'fold1|fold2|f3' skips fold1, fold2 and f3. --exclude 'fold1|fold2|f3' skips fold1, fold2 and f3.
--exclude reg : or this one, etc. --exclude reg : or this one, etc.
--automap : guesses folders mapping, for folders well known as
"Sent", "Junk", "Drafts", "All", "Archive", "Flagged".
--f1f2 str1=str2 : Force folder str1 to be synced to str2,
--f1f2 overrides --automap and --regextrans2.
--subfolder2 str : Move whole host1 folders hierarchy under this --subfolder2 str : Move whole host1 folders hierarchy under this
host2 folder str . host2 folder str .
It does it by adding two --regextrans2 options before It does it by adding two --regextrans2 options before
all others. Add --debug to see what's really going on. all others. Add --debug to see what's really going on.
--automap : guesses folders mapping, for folders like
"Sent", "Junk", "Drafts", "All", "Archive", "Flagged".
--f1f2 str1=str2 : Force folder str1 to be synced to str2,
--f1f2 overrides --automap and --regextrans2.
--nomixfolders : Avoid merging folders that are considered different on
host1 but the same on destination host2 because of
case sensitivities and insensitivities.
--subscribed : Transfers subscribed folders. --subscribed : Transfers subscribed folders.
--subscribe : Subscribe to the folders transferred on the --subscribe : Subscribe to the folders transferred on the
host2 that are subscribed on host1. On by default. host2 that are subscribed on host1. On by default.
@ -202,7 +218,7 @@ OPTIONS
Then, when happy, remove --dry, remove --justfolders. Then, when happy, remove --dry, remove --justfolders.
Have in mind that --regextrans2 is applied after prefix Have in mind that --regextrans2 is applied after prefix
and separator inversion. For examples see and separator inversion. For examples see
http://imapsync.lamiral.info/FAQ.d/FAQ.Folders_Mapping.txt https://imapsync.lamiral.info/FAQ.d/FAQ.Folders_Mapping.txt
OPTIONS/folders sizes OPTIONS/folders sizes
@ -254,6 +270,12 @@ OPTIONS
Example: 's/"Junk"//g' # to remove "Junk" flag. Example: 's/"Junk"//g' # to remove "Junk" flag.
--regexflag reg : then this one, etc. --regexflag reg : then this one, etc.
--resyncflags : Resync flags for already transferred messages.
On by default.
--noresyncflags : Do not resync flags for already transferred messages.
May be useful when a user has already started to play
with its host2 account.
OPTIONS/deletions OPTIONS/deletions
--delete1 : Deletes messages on host1 server after a successful --delete1 : Deletes messages on host1 server after a successful
@ -298,6 +320,8 @@ OPTIONS
a message arrived on a host (mtime). a message arrived on a host (mtime).
--idatefromheader : Sets the internal dates on host2 same as the --idatefromheader : Sets the internal dates on host2 same as the
"Date:" headers. "Date:" headers.
If you encounter problems with dates see also
https://imapsync.lamiral.info/FAQ.d/FAQ.Dates.txt
OPTIONS/message selection OPTIONS/message selection
@ -316,8 +340,11 @@ OPTIONS
--search str : Selects only messages returned by this IMAP SEARCH --search str : Selects only messages returned by this IMAP SEARCH
command. Applied on both sides. command. Applied on both sides.
--search1 str : Same as --search for selecting host1 messages only. For a complete of what can be search see
--search2 str : Same as --search for selecting host2 messages only. https://imapsync.lamiral.info/FAQ.d/FAQ.Messages_Selection.txt
--search1 str : Same as --search but for selecting host1 messages only.
--search2 str : Same as --search but for selecting host2 messages only.
--search CRIT equals --search1 CRIT --search2 CRIT --search CRIT equals --search1 CRIT --search2 CRIT
--maxlinelength int : skip messages with a line length longer than int bytes. --maxlinelength int : skip messages with a line length longer than int bytes.
@ -331,11 +358,11 @@ OPTIONS
--usecache : Use cache to speed up the sync. --usecache : Use cache to speed up the sync.
--nousecache : Do not use cache. Caveat: --useuid --nousecache creates --nousecache : Do not use cache. Caveat: --useuid --nousecache creates
duplicates on multiple runs. duplicates on multiple runs.
--useuid : Use uid instead of header as a criterium to recognize --useuid : Use UIDs instead of headers as a criterium to recognize
messages. Option --usecache is then implied unless messages. Option --usecache is then implied unless
--nousecache is used. --nousecache is used.
OPTIONS/miscelaneous OPTIONS/miscellaneous
--syncacls : Synchronizes acls (Access Control Lists). --syncacls : Synchronizes acls (Access Control Lists).
--nosyncacls : Does not synchronize acls. This is the default. --nosyncacls : Does not synchronize acls. This is the default.
@ -349,14 +376,14 @@ OPTIONS
--debugflags : Debug mode for flags. --debugflags : Debug mode for flags.
--debugimap1 : IMAP debug mode for host1. Very verbose. --debugimap1 : IMAP debug mode for host1. Very verbose.
--debugimap2 : IMAP debug mode for host2. Very verbose. --debugimap2 : IMAP debug mode for host2. Very verbose.
--debugimap : IMAP debug mode for host1 and host2. --debugimap : IMAP debug mode for host1 and host2. Twice very verbose.
--debugmemory : Debug mode showing memory consumption after each copy. --debugmemory : Debug mode showing memory consumption after each copy.
--errorsmax int : Exit when int number of errors is reached. Default is 50. --errorsmax int : Exit when int number of errors is reached. Default is 50.
--tests : Run local non-regression tests. Exit code 0 means all ok. --tests : Run local non-regression tests. Exit code 0 means all ok.
--testslive : Run a live test with test1.lamiral.info imap server. --testslive : Run a live test with test1.lamiral.info imap server.
Useful to check the basics. Needs internet connexion. Useful to check the basics. Needs internet connection.
--testslive6 : Run a live test with ks2ipv6.lamiral.info imap server. --testslive6 : Run a live test with ks2ipv6.lamiral.info imap server.
Useful to check the ipv6 connectivity. Needs internet. Useful to check the ipv6 connectivity. Needs internet.
@ -386,7 +413,7 @@ OPTIONS
On by default, 2 seconds max, like --maxsleep 2 On by default, 2 seconds max, like --maxsleep 2
--abort : terminates a previous call still running. --abort : terminates a previous call still running.
It uses the pidfile to know what processus to abort. It uses the pidfile to know what process to abort.
--exitwhenover int : Stop syncing when total bytes transferred reached. --exitwhenover int : Stop syncing when total bytes transferred reached.
@ -414,22 +441,24 @@ OPTIONS
SECURITY SECURITY
You can use --passfile1 instead of --password1 to give the password 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 since it is safer. With --password1 option, any user on your host can
the password by using the 'ps auxwwww' command. Using a variable (like see the password by using the 'ps auxwwww' command. Using a variable
$PASSWORD1) is also dangerous because of the 'ps auxwwwwe' command. So, (like $PASSWORD1) is also dangerous because of the 'ps auxwwwwe'
saving the password in a well protected file (600 or rw-------) is the command. So, saving the password in a well protected file (600 or
best solution. rw-------) is the best solution.
Imapsync activates ssl or tls encryption by default, if possible. What Imapsync activates ssl or tls encryption by default, if possible. What
details are under this "if possible"? Imapsync activates ssl if the well detailed behavior is under this "if possible"? Imapsync activates ssl if
known port imaps port (993) is open on the imap servers. If the imaps the well known port imaps port (993) is open on the imap servers. If the
port is closed then it open a normal (clear) connection on port 143 but imaps port is closed then it open a normal (clear) connection on port
it looks for TLS support in the CAPABILITY list of the servers. If TLS 143 but it looks for TLS support in the CAPABILITY list of the servers.
is supported then imapsync goes to encryption. If TLS is supported then imapsync goes to encryption.
If the automatic ssl/tls detection fails then imapsync will not protect If the automatic ssl/tls detection fails then imapsync will not protect
against sniffing activities on the network, especially for passwords. against sniffing activities on the network, especially for passwords.
If you want to force ssl or tls just use --ssl1 --ssl2 or --tls1 --tls2
See also the document FAQ.Security.txt in the FAQ.d/ directory or at See also the document FAQ.Security.txt in the FAQ.d/ directory or at
https://imapsync.lamiral.info/FAQ.d/FAQ.Security.txt https://imapsync.lamiral.info/FAQ.d/FAQ.Security.txt
@ -445,17 +474,17 @@ LICENSE AND COPYRIGHT
distribution or just read this simple sentence as it IS the licence distribution or just read this simple sentence as it IS the licence
text: text:
"No limit to do anything with this work and this license." "No limits to do anything with this work and this license."
In case it is not long enough, I repeat: In case it is not long enough, I repeat:
"No limit to do anything with this work and this license." "No limits to do anything with this work and this license."
https://imapsync.lamiral.info/LICENSE https://imapsync.lamiral.info/LICENSE
AUTHOR AUTHOR
Gilles LAMIRAL <gilles.lamiral@laposte.net> Gilles LAMIRAL <gilles@lamiral.info>
Feedback good or bad is very often welcome. Feedback good or bad is very often welcome.
@ -476,8 +505,8 @@ IMAP SERVERS supported
HUGE MIGRATION HUGE MIGRATION
Pay special attention to options --subscribed --subscribe --delete1 Pay special attention to options --subscribed --subscribe --delete1
--delete2 --delete2folders --maxage --minage --maxsize --useuid --delete1emptyfolders --delete2 --delete2folders --maxage --minage
--usecache --maxsize --useuid --usecache
If you have many mailboxes to migrate think about a little shell If you have many mailboxes to migrate think about a little shell
program. Write a file called file.txt (for example) containing users and program. Write a file called file.txt (for example) containing users and
@ -508,31 +537,36 @@ HUGE MIGRATION
in shell or batch programming ! in shell or batch programming !
You will find already written scripts at You will find already written scripts at
http://imapsync.lamiral.info/examples/ https://imapsync.lamiral.info/examples/
INSTALL INSTALL
Imapsync works under any Unix with perl. Imapsync works under any Unix with perl.
Imapsync works under Windows (2000, XP, Vista, Seven)
as a standalone binary software called imapsync.exe Imapsync works under most Windows (2000, XP, Vista, Seven, Eight, Ten
and all Server releases 2000, 2003, 2008 and R2, 2012 and R2)
as a standalone binary software called imapsync.exe,
usually launched from a batch file in order to avoid always typing
the options.
Imapsync works under OS X as a standalone binary Imapsync works under OS X as a standalone binary
software called imapsync_bin_Darwin. software called imapsync_bin_Darwin
Purchase latest imapsync at Purchase latest imapsync at
http://imapsync.lamiral.info/ https://imapsync.lamiral.info/
You'll receive a link to a compressed tarball called imapsync-x.xx.tgz 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 where x.xx is the version number. Untar the tarball where
you want (on Unix): you want (on Unix):
tar xzvf imapsync-x.xx.tgz tar xzvf imapsync-x.xx.tgz
Go into the directory imapsync-x.xx and read the INSTALL file. Go into the directory imapsync-x.xx and read the INSTALL file.
As mentioned at http://imapsync.lamiral.info/#install As mentioned at https://imapsync.lamiral.info/#install
the INSTALL file can also be found at the INSTALL file can also be found at
http://imapsync.lamiral.info/INSTALL https://imapsync.lamiral.info/INSTALL.d/INSTALL.ANY.txt
It is now split in several files for each system It is now split in several files for each system
http://imapsync.lamiral.info/INSTALL.d/ https://imapsync.lamiral.info/INSTALL.d/
CONFIGURATION CONFIGURATION
@ -543,17 +577,22 @@ HACKING
Feel free to hack imapsync as the NOLIMIT license permits it. Feel free to hack imapsync as the NOLIMIT license permits it.
SIMILAR SOFTWARES SIMILAR SOFTWARE
imap_tools : http://www.athensfbc.com/imap_tools See also https://imapsync.lamiral.info/S/external.shtml
for a better up to date list.
imap_tools : https://github.com/andrewnimmo/rick-sanders-imap-tools
offlineimap : https://github.com/nicolas33/offlineimap offlineimap : https://github.com/nicolas33/offlineimap
Doveadm-Sync : http://wiki2.dovecot.org/Tools/Doveadm/Sync
( Dovecot sync tool )
mbsync : http://isync.sourceforge.net/ mbsync : http://isync.sourceforge.net/
mailsync : http://mailsync.sourceforge.net/ mailsync : http://mailsync.sourceforge.net/
mailutil : http://www.washington.edu/imap/ mailutil : http://www.washington.edu/imap/
part of the UW IMAP tookit. part of the UW IMAP tookit.
imaprepl : http://www.bl0rg.net/software/ imaprepl : http://www.bl0rg.net/software/
http://freecode.com/projects/imap-repl/ http://freecode.com/projects/imap-repl/
imapcopy : http://home.arcor.de/armin.diehl/imapcopy/imapcopy.html imapcopy : http://www.ardiehl.de/imapcopy/
migrationtool : http://sourceforge.net/projects/migrationtool/ migrationtool : http://sourceforge.net/projects/migrationtool/
imapmigrate : http://sourceforge.net/projects/cyrus-utils/ imapmigrate : http://sourceforge.net/projects/cyrus-utils/
wonko_imapsync: http://wonko.com/article/554 wonko_imapsync: http://wonko.com/article/554
@ -567,11 +606,13 @@ HISTORY
I wrote imapsync because an enterprise (basystemes) paid me to install a I wrote imapsync because an enterprise (basystemes) paid me to install a
new imap server without losing huge old mailboxes located in a far away new imap server without losing huge old mailboxes located in a far away
remote imap server, accessible by a low-bandwidth link. The tool imapcp remote imap server, accessible by a low-bandwidth often broken link. The
(written in python) could not help me because I had to verify every tool imapcp (written in python) could not help me because I had to
mailbox was well transferred, and then delete it after a good transfer. verify every mailbox was well transferred, and then delete it after a
Imapsync started its life as a patch of the copy_folder.pl script. The good transfer. Imapsync started its life as a patch of the
script copy_folder.pl comes from the Mail-IMAPClient-2.1.3 perl module copy_folder.pl script. The script copy_folder.pl comes from the
tarball source (more precisely in the examples/ directory of the Mail-IMAPClient-2.1.3 perl module tarball source (more precisely in the
Mail-IMAPClient tarball). examples/ directory of the Mail-IMAPClient tarball). So many happened
since then that I wonder if it remains any lines of the original
copy_folder.pl in imapsync source code.

View File

@ -1,4 +1,4 @@
# $Id: README_Windows.txt,v 1.9 2017/09/11 02:57:38 gilles Exp gilles $ # $Id: README_Windows.txt,v 1.11 2018/05/05 22:46:01 gilles Exp gilles $
# #
# This is the README_Windows.txt file for imapsync # This is the README_Windows.txt file for imapsync
# imapsync : IMAP sync and migrate tool. # imapsync : IMAP sync and migrate tool.
@ -8,21 +8,21 @@ WINDOWS
There is two ways to install and use imapsync on Windows systems: A) or B). There is two ways to install and use imapsync on Windows systems: A) or B).
Standard users should only take the A) way. Standard users should take the A) way, the simplest way.
Developers, or powerful users that want to build their own imapsync.exe Developers, or powerful users that want to build their own imapsync.exe
or modify it, have to consider the B) way. or modify it, have to consider the B) way, the complex but powerful way.
A) Simplest way A) Simplest way
--------------- ---------------
A.1) Get imapsync. A.1) Get imapsync.
Get imapsync at https://imapsync.lamiral.info/dist/ Get imapsync at https://imapsync.lamiral.info/
You'll then have access to a zip archive file named imapsync_1.xxx.zip You'll then have access to a zip archive file named imapsync_1.xxx.zip
where 1.xxx is the imapsync release number. where 1.xxx is the imapsync release number.
A.2) Extract the zip file in a folder where you'll work with imapsync A.2) Extract the zip file in a folder where you will work with imapsync.
You can work on the Desktop since the zip file extraction creates You can work on the Desktop since the zip file extraction creates
a unique folder named imapsync_1.xxx (where 1.xxx is the imapsync a unique folder named imapsync_1.xxx (where 1.xxx is the imapsync
@ -32,22 +32,24 @@ A.3) Check the folder
In the folder extracted imapsync_1.xxx you see 6 files and 2 directories: In the folder extracted imapsync_1.xxx you see 6 files and 2 directories:
* README_Windows.txt is the current file you are reading * README_Windows.txt is the current file you are reading.
* README.txt is the imapsync general document. * README.txt is the imapsync general document.
* FAQ.d/* FAQs are a must read when something goes wrong. * FAQ.d/* FAQs are a good read when something goes wrong.
* imapsync_example.bat is a batch file example you will copy and edit * imapsync_example.bat is a simple batch file example you will copy and edit.
* sync_loop_windows.bat is a batch file example for syncing many accounts * sync_loop_windows.bat is a batch file example for syncing many accounts.
* file.txt is an input file example for syncing many accounts * file.txt is an input file example for syncing many accounts.
* imapsync.exe is the imapsync binary. You don't have to run it directly. * imapsync.exe is the imapsync binary. You don't have to run it directly.
* Cook/ is the directory to build imapsync.exe from its source. * Cook/ is the directory to build imapsync.exe from its source,
for the B) way and expert users.
You can copy or rename imapsync_example.bat as you wish as long as You can copy or rename imapsync_example.bat as you wish as long as
its extension remains ".bat". On Windows systems .bat extension its extension remains ".bat". On Windows systems .bat extension
means "I'm a batch script". Same thing for sync_loop_windows.bat. means "I'm a batch script". Same thing for sync_loop_windows.bat.
The batch scripts have to stay with imapsync.exe because The batch scripts have to stay in the same directory than
of the way they call it, they use ".\imapsync.exe", so imapsync.exe because of the way they call imapsync.exe,
let them be in the same directory (or change the path .\ they use ".\imapsync.exe", so let them be in the same directory.
to whatever you want if you understand what you're doing). Or change the path .\ to whatever you want if you understand what
you're doing.
For the rest of this documentation I assume you copied For the rest of this documentation I assume you copied
imapsync_example.bat to a file named imapsync_stuff.bat imapsync_example.bat to a file named imapsync_stuff.bat
@ -57,8 +59,9 @@ A.4) Edit the batch file
Edit imapsync_stuff.bat and change the values with yours. Edit imapsync_stuff.bat and change the values with yours.
In order to edit it you have do a right click on it and select "modify" In order to edit it you have do a right click on it and select "modify"
in the list presented in the small window menu. in the list presented in the small window menu.
Notepad or Notepadd++ are good editors to modify it. Notepad or Notepadd++ are very good editors to modify it.
Office Word is not good for that job, don't use it! Office Word or any powerful text processor are not good for that job,
don't use them!
Files FAQ.txt and FAQ.d/* contain many tips and special options sometimes Files FAQ.txt and FAQ.d/* contain many tips and special options sometimes
needed by specific imap server softwares like Exchange or Gmail. needed by specific imap server softwares like Exchange or Gmail.
@ -66,12 +69,12 @@ needed by specific imap server softwares like Exchange or Gmail.
A.5) Run the batch file A.5) Run the batch file
To run imapsync with your values just double-clic on To run imapsync with your values just double-click on
the batch file imapsync_stuff.bat the batch file imapsync_stuff.bat
You do not need to have administrator privilege to run imapsync. You do not need to have administrator privileges to run imapsync.
A.6) Loop on A.5) A.6) A.6) Loop on A.5) A.6) edit, run, edit, run etc.
Loop the process of editing and running imapsync until Loop the process of editing and running imapsync until
you solve all issues and all values suit your needs. you solve all issues and all values suit your needs.

18
S/bc-payment.html Executable file → Normal file
View File

@ -1,13 +1,21 @@
<!-- $Id: bc-payment.html,v 1.11 2017/09/11 03:04:46 gilles Exp gilles $ --> <!-- $Id: bc-payment.html,v 1.12 2018/02/07 01:03:31 gilles Exp gilles $ -->
<a <a
class="coinbase-button" class="coinbase-button"
href="https://www.coinbase.com/checkouts/5c8544cfe2d17f92401e60fd9299760f" data-code="6a986b9f1386effacf76b350070c93ab"
data-code="5c8544cfe2d17f92401e60fd9299760f">Pay with bitcoins</a> href="https://www.coinbase.com/checkouts/6a986b9f1386effacf76b350070c93ab"
><img
alt="Pay with Bitcoins"
src="S/images/bitcoin_buy_now_large.png"
/></a>
<!--
<script <script
src="https://www.coinbase.com/assets/button.js" src="https://www.coinbase.com/assets/button.js"
type="text/javascript"> >
</script> </script>
<!-- data-code="5c8544cfe2d17f92401e60fd9299760f" --> -->

1
S/button.js Normal file
View File

@ -0,0 +1 @@
(function(){var e,n,t,o;t=function(e,n){var t,o,a,r,i,s,c,d,u,m;return c=[null,null,!1],a=c[0],o=c[1],s=c[2],(a=window.jQuery)&&(u=parseInt(e.split(".")[0])||0,m=parseInt(e.split(".")[1])||0,r=parseInt(a.fn.jquery.split(".")[0])||0,i=parseInt(a.fn.jquery.split(".")[1])||0,t=r>u||r===u&&i>=m),a&&t?n(a):(d=document.createElement("script"),d.type="text/javascript",d.src="https://code.jquery.com/jquery-1.8.3.min.js",d.onload=d.onreadystatechange=function(){return s||(o=this.readyState)&&"loaded"!==o&&"complete"!==o?void 0:(n((a=window.jQuery).noConflict(1)),a(d).remove())},(document.getElementsByTagName("head")[0]||document.documentElement).appendChild(d))},e=function(e){return"development"===e||"test"===e?document.location.protocol+"//"+document.location.host:"https://www.coinbase.com"},n=function(t,o){var a,r;return window.coinbaseCookieLoaded?o(t):window.coinbaseCookieLoading?setTimeout(function(){return n(t,o)},200):(a=e(t("body").data("env")),window.coinbaseCookieLoading=!0,r=document.createElement("script"),r.src=a+"/checkouts/get_cookie.js",r.onload=r.onreadystatechange=function(){return window.coinbaseCookieLoaded=!0,window.coinbaseCookieLoading=!1,t(r).remove(),o(t)},(document.getElementsByTagName("head")[0]||document.documentElement).appendChild(r))},o=function(n){var t,o,a,r,i,s;return t=!1,o=!1,i=e(n("body").data("env")),s=function(e){var a,r,s;if(s=e.data.split("|"),r=s[0],a=s[1],a=escape(a),e.origin===i){if("show modal iframe"===r)return n("#coinbase_modal_iframe_"+a).show();if("coinbase_payment_complete"===r)return n("#coinbase_button_iframe_"+a).attr("src",i+"/buttons/paid"),n(document).trigger("coinbase_payment_complete",a);if("coinbase_payment_mispaid"===r)return n(document).trigger("coinbase_payment_mispaid",a);if("coinbase_payment_expired"===r)return n(document).trigger("coinbase_payment_expired",a);if("hide modal"===r)return n("#coinbase_modal_iframe_"+a).hide(),n(document).trigger("coinbase_modal_closed",a);if("signup redirect"===r)return document.location=i+"/users/verify";if("button frame loaded"===r){if(t=!0,o)return n(document).trigger("coinbase_button_loaded",a)}else if("checkouts frame loaded"===r&&(o=!0,t))return n(document).trigger("coinbase_button_loaded",a)}},r=function(e){switch(e){case"custom_large":return 276;case"custom_small":return 210;case"subscription_large":return 263;case"subscription_small":return 210;case"donation_large":return 189;case"donation_small":return 148;case"buy_now_large":return 211;case"buy_now_small":return 170;default:return 211}},a=function(e){switch(e){case"custom_large":return 62;case"custom_small":return 48;default:return 46}},window.addEventListener("message",s,!1),n(".coinbase-button").each(function(o){return function(o,s){var c,d,u,m,l,_,p,f;return c=n(s),m=c.data(),m.referrer=document.domain,p=n.param(m),u=c.data("code"),f=c.data("width")||r(c.data("button-style")),l=c.data("height")||a(c.data("button-style")),i=e(c.data("env")),d="<iframe src='"+i+"/buttons/"+u+"?"+p+"' id='coinbase_button_iframe_"+u+"' name='coinbase_button_iframe_"+u+"' style='width: "+f+"px; height: "+l+"px; border: none; overflow: hidden;' scrolling='no' allowtransparency='true' frameborder='0'></iframe>",_="<iframe src='"+i+"/checkouts/"+u+"/widget?"+p+"' id='coinbase_modal_iframe_"+u+"' name='coinbase_modal_iframe_"+u+"' style='background-color: transparent; border: 0px none transparent; display: none; position: fixed; visibility: visible; margin: 0px; padding: 0px; left: 0px; top: 0px; width: 100%; height: 100%; z-index: 9999;' scrolling='no' allowtransparency='true' frameborder='0'></iframe>","none"===c.data("button-style")?t=!0:c.replaceWith(d),n("body").append(_)}}(this)),n(document).on("coinbase_show_modal",function(e,t){return n("#coinbase_modal_iframe_"+t).length>0?(n("#coinbase_modal_iframe_"+t).show(),frames["coinbase_modal_iframe_"+t].postMessage("show modal|"+t,i)):void 0})},t("1.7",function(e){return n(e,o)})}).call(this);

30
S/external.shtml Executable file → Normal file
View File

@ -32,8 +32,9 @@
<ul> <ul>
<li> <b>imapsync</b>: <a href="https://github.com/imapsync/imapsync">https://github.com/imapsync/imapsync</a> (this is an imapsync copy, sometimes delayed)</li> <li> <b>imapsync</b>: <a href="https://github.com/imapsync/imapsync">https://github.com/imapsync/imapsync</a> (this is an imapsync copy, sometimes delayed)</li>
<li> imap_tools: <a href="https://web-beta.archive.org/web/20160927133511/http://www.athensfbc.com/imap-tools">http://www.athensfbc.com/imap_tools/</a></li> <li> imap_tools: <a href="https://web.archive.org/web/20161228145952/http://www.athensfbc.com/imap_tools/">http://www.athensfbc.com/imap_tools/</a>.
<li> imaputils: <a href="http://code.google.com/p/imaputils/">http://code.google.com/p/imaputils/</a> (imap_tools fork)</li> The imap_tools code is now at <a href="https://github.com/andrewnimmo/rick-sanders-imap-tools">https://github.com/andrewnimmo/rick-sanders-imap-tools</a></li>
<li> imaputils: <a href="http://code.google.com/p/imaputils/">http://code.google.com/p/imaputils/</a> (very old imap_tools fork)</li>
<li> Doveadm-Sync: <a href="http://wiki2.dovecot.org/Tools/Doveadm/Sync">http://wiki2.dovecot.org/Tools/Doveadm/Sync</a> ( Dovecot sync tool )</li> <li> Doveadm-Sync: <a href="http://wiki2.dovecot.org/Tools/Doveadm/Sync">http://wiki2.dovecot.org/Tools/Doveadm/Sync</a> ( Dovecot sync tool )</li>
<li> davmail: <a href="http://davmail.sourceforge.net/">http://davmail.sourceforge.net/</a></li> <li> davmail: <a href="http://davmail.sourceforge.net/">http://davmail.sourceforge.net/</a></li>
<li> <b>offlineimap</b>: <a href="http://offlineimap.org/">http://offlineimap.org/</a></li> <li> <b>offlineimap</b>: <a href="http://offlineimap.org/">http://offlineimap.org/</a></li>
@ -43,7 +44,7 @@
part of the UW IMAP tookit.</li> part of the UW IMAP tookit.</li>
<li> imaprepl: <a href="https://bl0rg.net/software/">https://bl0rg.net/software/</a> <li> imaprepl: <a href="https://bl0rg.net/software/">https://bl0rg.net/software/</a>
<a href="http://freecode.com/projects/imap-repl/">http://freecode.com/projects/imap-repl/</a></li> <a href="http://freecode.com/projects/imap-repl/">http://freecode.com/projects/imap-repl/</a></li>
<li> imapcopy (Pascal): <a href="http://home.arcor.de/armin.diehl/imapcopy/imapcopy.html">http://home.arcor.de/armin.diehl/imapcopy/imapcopy.html</a></li> <li> imapcopy (Pascal): <a href="http://www.ardiehl.de/imapcopy/">http://www.ardiehl.de/imapcopy/</a></li>
<li> imapcopy (Java): <a href="https://code.google.com/p/imapcopy/">https://code.google.com/p/imapcopy/</a></li> <li> imapcopy (Java): <a href="https://code.google.com/p/imapcopy/">https://code.google.com/p/imapcopy/</a></li>
<li> imapsize: <a href="http://www.broobles.com/imapsize/">http://www.broobles.com/imapsize/</a></li> <li> imapsize: <a href="http://www.broobles.com/imapsize/">http://www.broobles.com/imapsize/</a></li>
@ -55,6 +56,7 @@
<li> exchange-away: <a href="http://exchange-away.sourceforge.net/">http://exchange-away.sourceforge.net/</a></li> <li> exchange-away: <a href="http://exchange-away.sourceforge.net/">http://exchange-away.sourceforge.net/</a></li>
<li> SyncBackPro <a href="http://www.2brightsparks.com/syncback/sbpro.html">http://www.2brightsparks.com/syncback/sbpro.html</a></li> <li> SyncBackPro <a href="http://www.2brightsparks.com/syncback/sbpro.html">http://www.2brightsparks.com/syncback/sbpro.html</a></li>
<li> ImapSyncClient <a href="https://github.com/ridaamirini/ImapSyncClient">https://github.com/ridaamirini/ImapSyncClient</a></li>
</ul> </ul>
<h1>External online IMAP migration services <a id="ONLINE_OTHERS" href="../#TOP"><small>(back to menu)</small></a> <h1>External online IMAP migration services <a id="ONLINE_OTHERS" href="../#TOP"><small>(back to menu)</small></a>
@ -65,16 +67,16 @@ I don't think they use Imapsync.
Prices are given par mailbox and may be outdated (December 2011).</p> Prices are given par mailbox and may be outdated (December 2011).</p>
<ul> <ul>
<li> Imapsync.love <b>0 EUR</b>: <a href="http://imapsync.love/">http://imapsync.love/</a></li> <li> Imapsync.love <b>0 EUR</b>: <a href="http://imapsync.love/">http://imapsync.love/</a></li>
<li> French Ovh imapcopy <b>0 EUR</b>: <a href="https://mail.ovh.net/fr/imapcopy/">https://mail.ovh.net/fr/imapcopy/</a></li> <li> French Ovh imapcopy <b>0 EUR</b>: <a href="https://mail.ovh.net/fr/imapcopy/">https://mail.ovh.net/fr/imapcopy/</a></li>
<li> Turkish imapcopy.net <b>0 TRY</b>: <a href="http://imapcopy.net/">http://imapcopy.net/</a></li> <li> Rackspace migration <b>0 USD</b>: <a href="http://www.rackspace.com/email-hosting/migrations">http://www.rackspace.com/email-hosting/migrations</a></li>
<li> Rackspace migration <b>0 USD</b>: <a href="http://www.rackspace.com/email-hosting/migrations">http://www.rackspace.com/email-hosting/migrations</a></li> <li> Movemymail free for the first and 5 USD thereafter: <a href="https://movemymail.net">https://movemymail.net/</a></li>
<li> Movemymail free for the first and 5 USD thereafter: <a href="https://movemymail.net">https://movemymail.net</a> .</li> <li> TransferMyEmail <b>?? USD</b>: <a href="https://transfermyemail.ca/">https://transfermyemail.ca/</a></li>
<li> Migrationwiz 10 USD: <a href="https://www.bittitan.com/products/migrationwiz/">https://www.bittitan.com/products/migrationwiz/</a> <li> Migrationwiz 12 USD: <a href="https://www.bittitan.com/products/migrationwiz/">https://www.bittitan.com/products/migrationwiz/</a>
(See this remarkable comparaison <a href="https://blog.bittitan.com/imapsync-vs-migrationwiz/">Imapsync vs Migrationwiz</a>!)</li> ( See this remarkable comparison <a href="https://blog.bittitan.com/imapsync-vs-migrationwiz/">Imapsync vs Migrationwiz</a>! )</li>
<li> Audriga Gmbh 9.99 EUR: <a href="https://www.email-umzug.de/en.html">https://www.email-umzug.de/</a></li> <li> Audriga Gmbh 9.99 EUR: <a href="https://www.email-umzug.de/en.html">https://www.email-umzug.de/</a></li>
<li> Yippiemove 15 USD: <a href="http://www.yippiemove.com">http://www.yippiemove.com/</a></li> <li> Yippiemove 15 USD: <a href="http://www.yippiemove.com">http://www.yippiemove.com/</a>
<li> Dell ondemand-migration-for-email (price unknown): <a href="http://software.dell.com/products/ondemand-migration-for-email/">http://software.dell.com/products/ondemand-migration-for-email/</a></li> ( See <a href="https://www.yippiemove.com/help/faq_generic.html#imapsync">Yippiemove vs ImapSync</a> )</li>
</ul> </ul>
@ -105,7 +107,7 @@ alt="Viewable With Any Browser" />
<!--#config timefmt="%D" --> <!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" --> <!--#config timefmt="%A %B %d, %Y" -->
<b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b> <b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: external.shtml,v 1.20 2017/09/11 03:04:46 gilles Exp gilles $)<br/> ($Id: external.shtml,v 1.24 2018/05/05 22:51:15 gilles Exp gilles $)<br/>
<a href="#TOP">Top of the page</a> <a href="#TOP">Top of the page</a>
</p> </p>

34
S/guestbook.shtml Executable file → Normal file
View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" id="TOP"> <html lang="en" id="TOP">
<!-- $Id: guestbook.shtml,v 1.17 2017/09/11 03:04:46 gilles Exp gilles $ --> <!-- $Id: guestbook.shtml,v 1.19 2018/04/10 00:26:50 gilles Exp gilles $ -->
<head> <head>
<meta charset="utf-8" > <meta charset="utf-8" >
<title>Imapsync Guestbook</title> <title>Imapsync Guestbook</title>
@ -34,13 +34,13 @@ http://www.w3schools.com/html/html5_browsers.asp
<h1>Imapsync Guestbook</h1> <h1>Imapsync Guestbook</h1>
<p> <p>
Your name is mandatory to post but don't hesitate to use a pseudonym! Your name is mandatory to post but don't hesitate to use a pseudonym!
Email address is optional, only needed if you want a personnal reply. Email address is optional, only needed if you want a personal reply.
Have fun! Have fun!
</p> </p>
Feedback can also be done via: Feedback can also be done via:
<div class="email">An email to the author <a href="mailto:gilles.lamiral@laposte.net?subject=Imapsync_feedback" class="email">gilles.lamiral@laposte.net</a></div> <div class="email">An email to the author <a href="mailto:gilles@lamiral.info?subject=Imapsync_feedback" class="email">gilles@lamiral.info</a></div>
<div class="twitter">A tweet to the author <a href="https://twitter.com/imapsync" class="website">@imapsync</a></div> <div class="twitter">A tweet to the author <a href="https://twitter.com/imapsync" class="website">@imapsync</a></div>
@ -51,6 +51,34 @@ Feedback can also be done via:
</section> </section>
<footer> <footer>
<hr>
<a href="http://validator.w3.org/check?uri=referer">
<img
src="../S/images/valid-W3C-html5.png"
alt="Valid HTML5" height="31" width="88" >
</a>
<a href="http://jigsaw.w3.org/css-validator/check/referer">
<img style="border:0;width:88px;height:31px"
src="../S/images/vcss-blue"
alt="CSS Valide !" >
</a>
<a href="http://www.anybrowser.org/campaign/">
<img style="border:0;width:88px;height:31px"
src="../S/images/ab_jlh.png"
alt="Viewable With Any Browser" >
</a>
<hr>
<p>
<!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" -->
<b>This document was last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: guestbook.shtml,v 1.19 2018/04/10 00:26:50 gilles Exp gilles $)<br>
<a href="#TOP">Top of the page</a>
</p>
</footer> </footer>
</body> </body>
</html> </html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -1,959 +0,0 @@
#!/usr/bin/perl
# $Header: /mhub4/sources/imap-tools/IMAPtoMbox.pl,v 1.13 2015/04/30 12:22:21 rick Exp $
#######################################################################
# Program name IMAPtoMbox.pl #
# Written by Rick Sanders #
# #
# Description #
# #
# IMAPtoMbox.pl is a utility for extracting all of the mailboxes #
# in an IMAP user's account and writing them to files in the #
# Unix mbx format. #
# #
# The user supplies host/user/password information and the name #
# of a directory on the local system. IMAPtoMbox.pl connects to #
# the IMAP server and extracts each message in the user's IMAP #
# mailboxes. Those messages are written to a file with the same #
# name as the IMAP mailbox into the specified directory. #
# #
# For example: #
# ./IMAPtoMbox.pl -i localhost/rfs/mypass -m /var/rfs #
# #
# Optional arguments: #
# -d debug #
# -L logfile #
# -M IMAP mailbox list (dumps the specified mailboxes, see #
# the usage notes for syntax) #
#######################################################################
use Socket;
use FileHandle;
use Fcntl;
use Getopt::Std;
use MIME::Base64 qw(encode_base64 decode_base64);
use POSIX qw(strftime);
#################################################################
# Main program. #
#################################################################
$dir = init();
# Get list of all messages on the source host by Message-Id
#
connectToHost($sourceHost, \$dst);
login($sourceUser,$sourcePwd, $dst);
namespace($dst, \$prefix, \$delim );
@mbxs = getMailboxList( $prefix, $dst );
$number = $#mbxs + 1;
foreach $mbx ( @mbxs ) {
my $mbxname = $mbx;
$mbxname =~ s/^$prefix// if $prefix;
@msgs = ();
Log(" $mbxname");
getMsgList( $mbx, \@msgs, $dst );
$mbxname =~ s/\//-/g; # Don't allow slashes in filename
$mbxfn = "$dir/$mbxname";
if ( !open (M, ">>$mbxfn") ) {
Log("Error opening $mbxfn: $!");
print STDERR "Error opening $mbxfn\n";
next;
}
$summary{"$mbx"} = 0;
next if $#msgs == -1;
existingMboxMsgs( $mbxfn, \%mbox ) if $no_duplicates;
$copied=0;
next unless @msgs;
foreach $msg ( @msgs ) {
fetchMsg( $msg, $mbx, $dst, \$message, \$msgid );
if ( $no_duplicates and ($mbox{"$msgid"}) ) {
Log(" message $msgid already exists") if $debug;
next;
}
print M $message;
print M "\n";
$copied++;
if ( $msgs_per_folder ) {
# opt_F allows us to limit number of messages copied per folder
last if $copied == $msgs_per_folder;
}
}
close M;
`chown $opt_o "$mbxfn"` if $opt_o; # Set ownership
$summary{"$mbx"} = $copied++;
}
logout( $dst );
Log("\nSummary of results");
while (($x,$y) = each(%summary)) {
$x =~ s/^$prefix// if $prefix;
$line = pack("A50 A10\n", $x, $y);
push( @summary, $line );
}
@summary = sort @summary;
foreach $line ( @summary ) {
Log("$line");
}
exit;
sub init {
$os = $ENV{'OS'};
$dir = processArgs();
$timeout = 60 if !$timeout;
# Open the logFile
#
if ( $logfile ) {
if ( !open(LOG, ">> $logfile")) {
print STDOUT "Can't open $logfile: $!\n";
}
select(LOG); $| = 1;
}
Log("\n$0 starting");
Log("arguments i = $opt_i m = $opt_m");
Log("Mailfiles will be written to $dir");
# Determine whether we have SSL support via openSSL and IO::Socket::SSL
$ssl_installed = 1;
eval 'use IO::Socket::SSL';
if ( $@ ) {
$ssl_installed = 0;
}
$installed = 1;
@date_modules = qw( DateTime Date::Parse POSIX);
foreach $module ( @date_modules ) {
eval "use $module";
if ( $@ ) {
print STDERR "The Perl module $module is not installed. Please install it before proceeding.\n";
$installed = 0;
}
}
exit if $installed == 0;
return $dir;
}
#
# sendCommand
#
# This subroutine formats and sends an IMAP protocol command to an
# IMAP server on a specified connection.
#
sub sendCommand
{
local($fd) = shift @_;
local($cmd) = shift @_;
print $fd "$cmd\r\n";
if ($showIMAP) { Log (">> $cmd",2); }
}
#
# readResponse
#
# This subroutine reads and formats an IMAP protocol response from an
# IMAP server on a specified connection.
#
sub readResponse {
local($fd) = shift @_;
$response = <$fd>;
chop $response;
$response =~ s/\r//g;
push (@response,$response);
if ($showIMAP) { Log ("<< $response",2); }
}
#
# Log
#
# This subroutine formats and writes a log message to STDERR.
#
sub Log {
my $str = shift;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
if ($year < 99) { $yr = 2000; }
else { $yr = 1900; }
$line = sprintf ("%.2d-%.2d-%d.%.2d:%.2d:%.2d %s %s\n",
$mon + 1, $mday, $year + $yr, $hour, $min, $sec,$$,$str);
print LOG "$line";
print STDERR "$str\n";
}
# connectToHost
#
# Make a connection to a host
#
sub connectToHost {
my $host = shift;
my $conn = shift;
Log("Connecting to $host") if $debug;
($host,$port) = split(/:/, $host);
$port = 143 unless $port;
# We know whether to use SSL for ports 143 and 993. For any
# other ones we'll have to figure it out.
$mode = sslmode( $host, $port );
if ( $mode eq 'SSL' ) {
unless( $ssl_installed == 1 ) {
warn("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
Log("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
exit;
}
Log("Attempting an SSL connection") if $debug;
$$conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET,
);
unless ( $$conn ) {
$error = IO::Socket::SSL::errstr();
Log("Error connecting to $host: $error");
warn("Error connecting to $host: $error");
exit;
}
} else {
# Non-SSL connection
Log("Attempting a non-SSL connection") if $debug;
$$conn = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
);
unless ( $$conn ) {
Log("Error connecting to $host:$port: $@");
warn "Error connecting to $host:$port: $@";
exit;
}
}
Log("Connected to $host on port $port");
select( $$conn ); $| = 1;
while (1) {
readResponse ( $$conn );
if ( $response =~ /^\* OK/i ) {
last;
}
else {
Log ("Bad response from host on port $port: $response");
return 0;
}
}
Log ("connected to $host") if $debug;
select( $$conn ); $| = 1;
return 1;
}
sub sslmode {
my $host = shift;
my $port = shift;
my $mode;
# Determine whether to make an SSL connection
# to the host. Return 'SSL' if so.
if ( $port == 143 ) {
# Standard non-SSL port
return '';
} elsif ( $port == 993 ) {
# Standard SSL port
return 'SSL';
}
unless ( $ssl_installed ) {
# We don't have SSL installed on this machine
return '';
}
# For any other port we need to determine whether it supports SSL
my $conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
);
if ( $conn ) {
close( $conn );
$mode = 'SSL';
} else {
$mode = '';
}
return $mode;
}
# trim
#
# remove leading and trailing spaces from a string
sub trim {
local (*string) = @_;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return;
}
# login
#
# login in at the IMAP host with the user's name and password
#
sub login {
my $user = shift;
my $pwd = shift;
my $conn = shift;
if ( $admin_user ) {
# An AUTHENTICATE = PLAIN login has been requested
($authuser,$authpwd) = split(/:/, $admin_user );
login_plain( $user, $authuser, $authpwd, $conn ) or exit;
return 1;
}
if ( $pwd =~ /^oauth2:(.+)/i ) {
$token = $1;
Log("password is an OAUTH2 token") if $debug;
login_xoauth2( $user, $token, $conn );
return 1;
}
sendCommand ($conn, "1 LOGIN $user \"$pwd\"");
while (1) {
readResponse ( $conn );
if ($response =~ /^1 OK/i) {
last;
}
elsif ($response =~ /NO/) {
Log ("unexpected LOGIN response: $response");
exit;
}
}
Log("Logged in as $user") if $debug;
return 1;
}
# login_plain
#
# login in at the source host with the user's name and password. If provided
# with administrator credential, use them as this eliminates the need for the
# user's password.
#
sub login_plain {
my $user = shift;
my $admin = shift;
my $pwd = shift;
my $conn = shift;
# Do an AUTHENTICATE = PLAIN. If an admin user has been provided then use it.
if ( !$admin ) {
# Log in as the user
$admin = $user
}
$login_str = sprintf("%s\x00%s\x00%s", $user,$admin,$pwd);
$login_str = encode_base64("$login_str", "");
$len = length( $login_str );
sendCommand ($conn, "1 AUTHENTICATE PLAIN" );
my $loops;
while (1) {
readResponse ( $conn );
last if $response =~ /\+/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
sendCommand ($conn, "$login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /Microsoft Exchange/i and $conn eq $dst ) {
# The destination is an Exchange server
$exchange = 1;
Log("The destination is an Exchange server");
}
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
return 1;
}
# logout
#
# log out from the host
#
sub logout {
my $conn = shift;
++$lsn;
undef @response;
sendCommand ($conn, "$lsn LOGOUT");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^$lsn OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected LOGOUT response: $response");
last;
}
}
close $conn;
return;
}
# getMailboxList
#
# get a list of the user's mailboxes from the source host
#
sub getMailboxList {
my $prefix = shift;
my $conn = shift;
my @mbxs;
# Get a list of the user's mailboxes
#
Log("Get list of user's mailboxes",2) if $debugMode;
if ( $mbxList ) {
foreach $mbx ( split(/,/, $mbxList) ) {
$mbx = $prefix . $mbx if $prefix;
if ( $opt_r ) {
# Get all submailboxes under the ones specified
$mbx .= '*';
@mailboxes = listMailboxes( $mbx, $conn);
push( @mbxs, @mailboxes );
} else {
push( @mbxs, $mbx );
}
}
} else {
# Get all mailboxes
@mbxs = listMailboxes( '*', $conn);
}
return @mbxs;
}
# listMailboxes
#
sub listMailboxes {
my $mbx = shift;
my $conn = shift;
sendCommand ($conn, "1 LIST \"\" \"$mbx\"");
undef @response;
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
return 0;
}
}
%nosel_mbxs = ();
@mbxs = ();
for $i (0 .. $#response) {
$response[$i] =~ s/\s+/ /;
if ( $response[$i] =~ /"$/ ) {
$response[$i] =~ /\* LIST \((.*)\) "(.+)" "(.+)"/i;
$mbx = $3;
} else {
$response[$i] =~ /\* LIST \((.*)\) "(.+)" (.+)/i;
$mbx = $3;
}
$mbx =~ s/^\s+//; $mbx =~ s/\s+$//;
next if $response[$i] =~ /NOSELECT/i;
if (($mbx =~ /^\#/) && ($user ne 'anonymous')) {
# Skip public mbxs unless we are migrating them
next;
}
if ($mbx =~ /^\./) {
# Skip mailboxes starting with a dot
next;
}
push ( @mbxs, $mbx ) if $mbx ne '';
}
return @mbxs;
}
# getMsgList
#
# Get a list of the user's messages in the indicated mailbox on
# the source host
#
sub getMsgList {
my $mailbox = shift;
my $msgs = shift;
my $conn = shift;
my $seen;
my $empty;
my $msgnum;
my $from;
trim( *mailbox );
sendCommand ($conn, "1 EXAMINE \"$mailbox\"");
undef @response;
$empty=0;
select($conn);
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ / 0 EXISTS/i ) { $empty=1; }
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
# print STDERR "Error: $response\n";
return 0;
}
}
return if $empty;
Log("Fetch the header info") if $debug;
sendCommand ( $conn, "1 FETCH 1:* (uid flags internaldate body[header.fields (From Date)])");
undef @response;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
}
}
undef @msgs;
undef $flags;
for $i (0 .. $#response) {
$seen=0;
$_ = $response[$i];
last if /OK FETCH complete/;
if ( $response[$i] =~ /^From:\s*(.+)/i ) {
$from = $1 if !$from;
}
if ( $response[$i] =~ /^Date: (.+)/ ) {
# Firstly assume that the date is formatted correctly and split accordingly.
$origdate = $1;
$date = $origdate;
$date =~ s/,//g;
($date) = split(/-/, $date);
($wkday,$mday,$mon,$yr,$time) = split(/\s+/, $date);
$mday = '0' . $mday if length($mday) == 1;
$date = "$wkday $mon $mday $time $yr";
# Now actually parse the date to check that it is formatted correctly.
# Assume GMT if timezone is omitted.
my @parseddate = strptime ($origdate, "GMT");
# If the number of seconds were omitted then assume 0.
if ( !defined $parseddate[0] ) {
$parseddate[0] = 0;
}
# If the year was given as 2 digits, assume it can't be less than the UNIX epoch of 1970.
if ( $parseddate[5] < 70 ) {
$parseddate[5] += 100;
}
# strptime returns the timezone as an offset in seconds. Convert back to +/-HHMM format.
if ( $parseddate[6] < 0 ) {
$parseddate[6] = sprintf ("-%02d%02d", int (-$parseddate[6] / 3600), int ((-$parseddate[6] % 3600) / 60));
} else {
$parseddate[6] = sprintf ("+%02d%02d", int ($parseddate[6] / 3600), int (($parseddate[6] % 3600) / 60));
}
eval '
$dt = DateTime->new (second => $parseddate[0],
minute => $parseddate[1],
hour => $parseddate[2],
day => $parseddate[3],
month => $parseddate[4] + 1, # needs to be 1-12 and not 0-11.
year => $parseddate[5] + 1900, # needs to be an absolute year.
time_zone => $parseddate[6]);
';
if ( length( $@ ) != 0 ) {
# The date is too badly formatted to fix. Use today's date instead.
Log("The date $date is badly formatted, using today's date instead");
$date = strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time()));
} else {
$newdate = $dt->strftime ("%a %b %d %H:%M:%S %Y");
# Compare the parsed date with that formed by assuming the date was correctly formatted.
# Let the user know if they differ so they can judge if the calculated date is correct.
if ( $date ne $newdate ) {
Log ("badly formatted date in message: " . $origdate);
Log (" calculated replacement date as: " . $newdate);
$date = $newdate;
}
}
}
if ( $response[$i] =~ /\* (.+) FETCH/ ) {
($msgnum) = split(/\s+/, $1);
}
if ( $response[$i] =~ /^\)/ or ( $response[$i] =~ /\)\)$/ ) ) {
push (@$msgs,"$msgnum|$from|$date");
$msgnum = $date = '';
}
}
}
#
## Fetch a message from the IMAP server
#
sub fetchMsg {
my $msg = shift;
my $mbx = shift;
my $conn = shift;
my $message = shift;
my $msgid = shift;
my ($msgnum,$from,$date) = split(/\|/, $msg);
Log(" Fetching msg $msgnum...") if $debug;
sendCommand ($conn, "1 EXAMINE \"$mbx\"");
while (1) {
readResponse ($conn);
last if ( $response =~ /^1 OK/i );
}
sendCommand( $conn, "1 FETCH $msgnum (rfc822)");
while (1) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
$size = length($message);
last;
}
elsif ( $response =~ /^1 NO|^1 BAD/ ) {
last;
}
elsif ($response =~ /message number out of range/i) {
Log ("Error fetching uid $uid: out of range",2);
$stat=0;
last;
}
elsif ($response =~ /Bogus sequence in FETCH/i) {
Log ("Error fetching uid $uid: Bogus sequence in FETCH",2);
$stat=0;
last;
}
elsif ( $response =~ /message could not be processed/i ) {
Log("Message could not be processed, skipping it ($user,msgnum $msgnum,$destMbx)");
push(@errors,"Message could not be processed, skipping it ($user,msgnum $msgnum,$destMbx)");
$stat=0;
last;
}
elsif
($response =~ /^\*\s+$msgnum\s+FETCH\s+\(.*RFC822\s+\{[0-9]+\}/i) {
($len) = ($response =~ /^\*\s+$msgnum\s+FETCH\s+\(.*RFC822\s+\{([0-9]+)\}/i);
$cc = 0;
$$message = "";
while ( $cc < $len ) {
$n = 0;
$n = read ($conn, $segment, $len - $cc);
if ( $n == 0 ) {
Log ("unable to read $len bytes");
return 0;
}
$$message .= $segment;
$cc += $n;
}
}
}
$$message =~ s/\r//g;
if ( $$message !~ /^From / ) {
$$message = "From $from $date\n$$message";
}
# Some servers don't like single-digit days in the timestamp
# in the "From " line
for $i (0 .. 9 ) {
$$message =~ s/ $i / 0$i /;
}
$$message =~ /Message-ID:\s*\<(.+)\>/i;
$$msgid = $1 if $1;
}
#
## Display the usage message
#
sub usage {
print STDOUT "\nusage:";
print STDOUT "IMAPtoMbox.pl -i Host/User/Password -m <dir> [-M] [-d] [-I] [-o <user>] \n";
print STDOUT "\n Optional arguments:\n";
print STDOUT " -M IMAP mailbox list (eg \"Inbox, Drafts, Notes\". Default all mailboxes)\n";
print STDOUT " -o <user> sets ownership of mailfile\n";
print STDOUT " -A <admin_user:admin_pwd>\n";
print STDOUT " -L logfile\n";
print STDOUT " -d debug\n";
print STDOUT " -I show IMAP protocal exchanges\n";
print STDOUT " -n don't copy if message already exists in mbox file\n";
print STDOUT " -r include submailboxes when used with -M\n\n";
exit;
}
#
## Get command-line arguments
#
sub processArgs {
if ( !getopts( "di:L:m:hM:Io:nrF:A:" ) ) {
usage();
}
($sourceHost,$sourceUser,$sourcePwd) = split(/\//, $opt_i);
$mbxList = $opt_M;
$logfile = $opt_L;
$dir = $opt_m;
$owner = $opt_o;
$no_duplicates = 1 if $opt_n;
$submbxs = 1 if $opt_r;
$debug = 1 if $opt_d;
$showIMAP = 1 if $opt_I;
$msgs_per_folder = $opt_F;
$admin_user = $opt_A;
if ( !$dir ) {
print "You must specify the file directory where messages will\n";
print "be written using the -m argument.\n\n";
usage();
exit;
}
if ( !-d $dir ) {
print "Fatal Error: $dir does not exist\n";
exit;
}
usage() if $opt_h;
return $dir;
}
sub existingMboxMsgs {
my $mbx = shift;
my $msgs = shift;
# Build an index of messages in an mbox by messageID.
%$msgs = ();
unless ( open(F, "<$mbx") ) {
Log("Error opening mbox file $mbox: $!");
return;
}
while ( <F> ) {
if ( /^Message-ID:\s*\<(.+)\>/i ) {
$$msgs{"$1"} = 1;
}
}
close F;
}
sub namespace {
my $conn = shift;
my $prefix = shift;
my $delimiter = shift;
# Query the server with NAMESPACE so we can determine its
# mailbox prefix (if any) and hierachy delimiter.
@response = ();
sendCommand( $conn, "1 NAMESPACE");
while ( 1 ) {
readResponse( $conn );
if ( $response =~ /^1 OK/i ) {
last;
} elsif ( $response =~ /NO|BAD/i ) {
Log("Unexpected response to NAMESPACE command: $response");
last;
}
}
foreach $_ ( @response ) {
if ( /NAMESPACE/i ) {
my $i = index( $_, '((' );
my $j = index( $_, '))' );
my $val = substr($_,$i+2,$j-$i-3);
($val) = split(/\)/, $val);
($$prefix,$$delimiter) = split( / /, $val );
$$prefix =~ s/"//g;
$$delimiter =~ s/"//g;
last;
}
last if /^NO|^BAD/;
}
if ( $debug ) {
Log("prefix $$prefix");
Log("delim $$delimiter");
}
}
sub mailboxName {
my $mbx = shift;
my $prefix = shift;
my $delim = shift;
# Adjust the mailbox name if necessary using the mailbox hierarchy
# prefix and delimiter.
$mbx =~ s#^$srcPrefix##;
$mbx = $srcmbx;
if ( $srcDelim ne $dstDelim ) {
# Need to substitute the dst's hierarchy delimiter for the src's one
$srcDelim = '\\' . $srcDelim if $srcDelim eq '.';
$dstDelim = "\\" . $dstDelim if $dstDelim eq '.';
$dstmbx =~ s#$srcDelim#$dstDelim#g;
$dstmbx =~ s/\\//g;
}
if ( $srcPrefix ne $dstPrefix ) {
# Replace the source prefix with the dest prefix
$dstmbx =~ s#^$srcPrefix## if $srcPrefix;
if ( $dstPrefix ) {
$dstmbx = "$dstPrefix$dstmbx" unless uc($srcmbx) eq 'INBOX';
}
$dstDelim = "\\$dstDelim" if $dstDelim eq '.';
$dstmbx =~ s#^$dstDelim##;
}
if ( $root_mbx ) {
# Put folders under a 'root' folder on the dst
$dstDelim =~ s/\./\\./g;
$dstmbx =~ s/^$dstPrefix//;
$dstmbx =~ s/^$dstDelim//;
$dstmbx = $dstPrefix . $root_mbx . $dstDelim . $dstmbx;
if ( uc($srcmbx) eq 'INBOX' ) {
# Special case for the INBOX
$dstmbx =~ s/INBOX$//i;
$dstmbx =~ s/$dstDelim$//;
}
$dstmbx =~ s/\\//g;
}
return $dstmbx;
}
# login_xoauth2
#
# login in at the source host with the user's name and an XOAUTH2 token.
#
sub login_xoauth2 {
my $user = shift;
my $token = shift;
my $conn = shift;
# Do an AUTHENTICATE = XOAUTH2 login
$login_str = encode_base64("user=". $user ."\x01auth=Bearer ". $token ."\x01\x01", '');
sendCommand ($conn, "1 AUTHENTICATE XOAUTH2 $login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /^\+ (.+)/ ) {
$error = decode_base64( $1 );
Log("XOAUTH authentication as $user failed: $error");
exit;
}
last if $response =~ /^1 OK/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE|failed/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
Log("login complete") if $debug;
return 1;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,924 +0,0 @@
#!/usr/bin/perl
# $Header: /mhub4/sources/imap-tools/dumptoIMAP.pl,v 1.14 2014/11/10 12:55:43 rick Exp $
#######################################################################
# dumptoIMAP.pl is used to load the mailboxes and messages exported #
# from an IMAP server by the imapdump.pl script. See usage() notes #
# for a list of the arguments used to run it. #
# #
# If you ran imapdump.pl -S host/user/pwd -f /tmp/BACKUP #
# then you could restore all of the mailboxes & messages with the #
# following command: #
# #
# ./dumptoIMAP.pl -i host/user/pwd -D /tmp/BACKUP #
# #
# If you wanted to restore just the INBOX and the Sent mailboxes you #
# would add -m "INBOX,Sent" #
#######################################################################
use Socket;
use IO::Socket;
use FileHandle;
use File::Find;
use Fcntl;
use Getopt::Std;
use MIME::Base64 qw(decode_base64 encode_base64);
init();
connectToHost($imapHost, \$conn);
if ( $imapUser =~ /(.+):(.+)/ ) {
# An AUTHENTICATE = PLAIN login has been requested
$imapUser = $1;
$authuser = $2;
login_plain( $imapUser, $authuser, $imapPwd, $conn ) or exit;
} else {
if ( !login($imapUser,$imapPwd, $conn) ) {
Log("Check your username and password");
print STDOUT "Login failed: Check your username and password\n";
exit;
}
}
if ( $opt_y ) {
# User-supplied mbx delimiter and prefix
($mbx_delim,$prefix) = split(/\s+/, $opt_y );
} else {
namespace( $conn, \$prefix, \$mbx_delim );
}
get_mbx_list( $dir, \@mbxs );
foreach $mbx ( @mbxs ) {
$copied=0;
Log("mbx = >$mbx<") if $debug;
Log("Full path to $mbx is >$dir/$mbx<") if $debug;
Log("Copying messages from $dir/$mbx to $mbx folder on the IMAP server");
get_messages( "$dir/$mbx", \@msgs );
$n = scalar @msgs;
Log("$mbx has $n messages");
$mbx =~ s/\//$mbx_delim/g unless $mbx_delim eq '/';
if ( $prefix ) {
$mbx = $prefix . $mbx unless $mbx =~ /^INBOX/i;
}
foreach $_ ( @msgs ) {
next unless $_;
my $msg; my $date; my $seen;
$flags = '';
if ( /,S$/ ) {
$flags = '\\SEEN';
}
Log("Opening $_") if $debug;
unless ( open(F, "<$_") ) {
Log("Error opening $_: $!");
next;
}
Log("Opened $_ successfully") if $debug;
while( <F> ) {
# Log("Reading line $_") if $debug;
if ( /^Date: (.+)/ ) {
$date = $1 unless $date;
$date =~ s/\r|\m//g;
chomp $date;
}
s/\r+$//g;
$msg .= $_;
chomp $msg;
$msg .= "\r\n";
}
close F;
$size = length( $msg );
Log("The message is $size bytes") if $debug;
# Log("$msg") if $debug;
if ( $size == 0 ) {
Log("The message file is empty") if $debug;
next;
}
$copied++ if insertMsg($mbx, \$msg, $flags, $date, $conn);
if ( $msgs_per_folder ) {
# opt_F allows us to limit number of messages copied per folder
last if $copied == $msgs_per_folder;
}
if ( $copied/100 == int($copied/100)) { Log("$copied messages copied "); }
}
$total += $copied;
}
logout( $conn );
Log("Done. $total messages were copied.");
exit;
sub init {
if ( !getopts('m:L:i:dD:Ix:XRA:F:y:') ) {
usage();
}
$mbx_list = $opt_m;
$dir = $opt_D;
$logfile = $opt_L;
$extension = $opt_x;
$debug = 1 if $opt_d;
$showIMAP = 1 if $opt_I;
$admin_user = $opt_A;
$msgs_per_folder = $opt_F;
($imapHost,$imapUser,$imapPwd) = split(/\//, $opt_i);
if ( $logfile ) {
if ( ! open (LOG, ">> $logfile") ) {
print "Can't open logfile $logfile: $!\n";
$logfile = '';
}
}
Log("Starting");
# Determine whether we have SSL support via openSSL and IO::Socket::SSL
$ssl_installed = 1;
eval 'use IO::Socket::SSL';
if ( $@ ) {
$ssl_installed = 0;
}
}
sub usage {
print "Usage: dumptoIMAP.pl\n";
print " -D <path to the mailboxes>\n";
print " -i <server/username/password>\n";
print " (if the password is an OAUTH2 token then prefix it with 'oauth2:'\n";
print " [-A <admin_user:admin_pwd>\n";
print " [-m <mbx1,mbx2,..,mbxn> copy only the listed mailboxes]\n";
print " [-x <extension> Import only files with this extension\n";
print " [-L <logfile>]\n";
print " [-d debug]\n";
print " [-I log IMAP protocol exchanges]\n";
}
sub get_messages {
my $dir = shift;
my $msgs = shift;
# Get a list of the message files
if ( $debug ) {
Log("Get list of messages in $dir");
}
opendir D, $dir;
my @files = readdir( D );
closedir D;
foreach $_ ( @files ) {
next if /^\./;
if ( $extension ) {
next unless /$extension$/;
}
Log(" $dir/$_") if $debug;
push( @$msgs, "$dir/$_");
}
}
# Print a message to STDOUT and to the logfile if
# the opt_L option is present.
#
sub Log {
my $line = shift;
my $msg;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime (time);
$msg = sprintf ("%.2d-%.2d-%.4d.%.2d:%.2d:%.2d %s",
$mon + 1, $mday, $year + 1900, $hour, $min, $sec, $line);
if ( $logfile ) {
print LOG "$msg\n";
}
print STDOUT "$line\n";
}
# connectToHost
#
# Make an IMAP connection to a host
#
sub connectToHost {
my $host = shift;
my $conn = shift;
Log("Connecting to $host") if $debug;
$sockaddr = 'S n a4 x8';
($name, $aliases, $proto) = getprotobyname('tcp');
($host,$port) = split(/:/, $host);
$port = 143 unless $port;
if ($host eq "") {
Log ("no remote host defined");
close LOG;
exit (1);
}
# We know whether to use SSL for ports 143 and 993. For any
# other ones we'll have to figure it out.
$mode = sslmode( $host, $port );
if ( $mode eq 'SSL' ) {
unless( $ssl_installed == 1 ) {
warn("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
Log("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
exit;
}
Log("Attempting an SSL connection") if $debug;
$$conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET,
);
unless ( $$conn ) {
$error = IO::Socket::SSL::errstr();
Log("Error connecting to $host: $error");
exit;
}
} else {
# Non-SSL connection
Log("Attempting a non-SSL connection") if $debug;
$$conn = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
);
unless ( $$conn ) {
Log("Error connecting to $host:$port: $@");
warn "Error connecting to $host:$port: $@";
exit;
}
}
select( $$conn ); $| = 1;
return 1;
}
#
# login in at the IMAP host with the user's name and password
#
sub login {
my $user = shift;
my $pwd = shift;
my $conn = shift;
if ( $admin_user ) {
# An AUTHENTICATE = PLAIN login has been requested
($authuser,$authpwd) = split(/:/, $admin_user );
login_plain( $user, $authuser, $authpwd, $conn ) or exit;
return 1;
}
if ( $pwd =~ /^oauth2:(.+)/i ) {
$token = $1;
Log("password is an OAUTH2 token");
login_xoauth2( $user, $token, $conn );
return 1;
}
Log("Logging in as $user") if $debug;
$rsn = 1;
sendCommand ($conn, "$rsn LOGIN $user $pwd");
while (1) {
readResponse ( $conn );
if ($response =~ /^$rsn OK/i) {
last;
}
elsif ($response =~ /NO/) {
Log ("unexpected LOGIN response: $response");
return 0;
}
}
Log("Logged in as $user") if $debug;
return 1;
}
# login_plain
#
# login in at the source host with the user's name and password. If provided
# with administrator credential, use them as this eliminates the need for the
# user's password.
#
sub login_plain {
my $user = shift;
my $admin = shift;
my $pwd = shift;
my $conn = shift;
# Do an AUTHENTICATE = PLAIN. If an admin user has been provided then use it.
if ( !$admin ) {
# Log in as the user
$admin = $user
}
$login_str = sprintf("%s\x00%s\x00%s", $user,$admin,$pwd);
$login_str = encode_base64("$login_str", "");
$len = length( $login_str );
# sendCommand ($conn, "1 AUTHENTICATE \"PLAIN\" {$len}" );
sendCommand ($conn, "1 AUTHENTICATE PLAIN $login_str" );
my $loops;
while (1) {
readResponse ( $conn );
last if $response =~ /^1 OK/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
return 1;
}
# login_xoauth2
#
# login in at the source host with the user's name and an XOAUTH2 token.
#
sub login_xoauth2 {
my $user = shift;
my $token = shift;
my $conn = shift;
# Do an AUTHENTICATE = XOAUTH2 login
$login_str = encode_base64("user=". $user ."\x01auth=Bearer ". $token ."\x01\x01", '');
sendCommand ($conn, "1 AUTHENTICATE XOAUTH2 $login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /^\+ (.+)/ ) {
$error = decode_base64( $1 );
Log("XOAUTH authentication as $user failed: $error");
exit;
}
last if $response =~ /^1 OK/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE|failed/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
Log("login complete") if $debug;
return 1;
}
# logout
#
# log out from the host
#
sub logout {
my $conn = shift;
++$lsn;
undef @response;
sendCommand ($conn, "$lsn LOGOUT");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^$lsn OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected LOGOUT response: $response");
last;
}
}
close $conn;
return;
}
# readResponse
#
# This subroutine reads and formats an IMAP protocol response from an
# IMAP server on a specified connection.
#
sub readResponse {
my $fd = shift;
$response = <$fd>;
chop $response;
$response =~ s/\r//g;
push (@response,$response);
Log(">>$response") if $showIMAP;
}
#
# sendCommand
#
# This subroutine formats and sends an IMAP protocol command to an
# IMAP server on a specified connection.
#
sub sendCommand {
my $fd = shift;
my $cmd = shift;
print $fd "$cmd\r\n";
Log(">>$cmd") if $showIMAP;
}
#
# insertMsg
#
# Append a message to an IMAP mailbox
#
sub insertMsg {
my $mbx = shift;
my $message = shift;
my $flags = shift;
my $date = shift;
my $conn = shift;
my ($lsn,$lenx);
Log(" Inserting message") if $debug;
$lenx = length($$message);
# Log("$$message");
($date) = split(/\s*\(/, $date);
if ( $date =~ /,/ ) {
$date =~ /(.+),\s+(.+)\s+(.+)\s+(.+)\s+(.+)\s+(.+)/;
$date = "$2-$3-$4 $5 $6";
} else {
$date =~ s/\s/-/;
$date =~ s/\s/-/;
}
# Create the mailbox unless we have already done so
++$lsn;
if ($destMbxs{"$mbx"} eq '') {
sendCommand ($conn, "$lsn CREATE \"$mbx\"");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^$rsn OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
if (!($response =~ /already exists|reserved mailbox name/i)) {
Log ("WARNING: $response");
}
last;
}
}
}
$destMbxs{"$mbx"} = '1';
$flags =~ s/\\Recent//i;
if ( $date ) {
sendCommand ($conn, "1 APPEND \"$mbx\" ($flags) \"$date\" \{$lenx\}");
} else {
sendCommand ($conn, "1 APPEND \"$mbx\" ($flags) \{$lenx\}");
}
readResponse ($conn);
if ( $response !~ /^\+/ ) {
Log ("unexpected APPEND response to $cmd");
push(@errors,"Error appending message to $mbx for $user");
return 0;
}
if ( $opt_X ) {
print $conn "$$message\n";
} else {
print $conn "$$message\r\n";
}
undef @response;
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^$lsn OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected APPEND response: $response");
return 0;
}
}
return 1;
}
# getMsgList
#
# Get a list of the user's messages in the indicated mailbox on
# the IMAP host
#
sub getMsgList {
my $mailbox = shift;
my $msgs = shift;
my $conn = shift;
my $seen;
my $empty;
my $msgnum;
Log("Getting list of msgs in $mailbox") if $debug;
trim( *mailbox );
sendCommand ($conn, "$rsn EXAMINE \"$mailbox\"");
undef @response;
$empty=0;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ / 0 EXISTS/i ) { $empty=1; }
if ( $response =~ /^$rsn OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
return 0;
}
}
sendCommand ( $conn, "$rsn FETCH 1:* (uid flags internaldate body[header.fields (Message-Id)])");
undef @response;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ /^$rsn OK/i ) {
last;
}
}
# Get a list of the msgs in the mailbox
#
undef @msgs;
undef $flags;
for $i (0 .. $#response) {
$seen=0;
$_ = $response[$i];
last if /OK FETCH complete/;
if ( $response[$i] =~ /FETCH \(UID / ) {
$response[$i] =~ /\* ([^FETCH \(UID]*)/;
$msgnum = $1;
}
if ($response[$i] =~ /FLAGS/) {
# Get the list of flags
$response[$i] =~ /FLAGS \(([^\)]*)/;
$flags = $1;
$flags =~ s/\\Recent//i;
}
if ( $response[$i] =~ /INTERNALDATE ([^\)]*)/ ) {
### $response[$i] =~ /INTERNALDATE (.+) ([^BODY]*)/i;
$response[$i] =~ /INTERNALDATE (.+) BODY/i;
$date = $1;
$date =~ s/"//g;
}
if ( $response[$i] =~ /^Message-Id:/i ) {
($label,$msgid) = split(/: /, $response[$i]);
push (@$msgs,$msgid);
}
}
}
# trim
#
# remove leading and trailing spaces from a string
sub trim {
local (*string) = @_;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return;
}
sub sslmode {
my $host = shift;
my $port = shift;
my $mode;
# Determine whether to make an SSL connection
# to the host. Return 'SSL' if so.
if ( $port == 143 ) {
# Standard non-SSL port
return '';
} elsif ( $port == 993 ) {
# Standard SSL port
return 'SSL';
}
unless ( $ssl_installed ) {
# We don't have SSL installed on this machine
return '';
}
# For any other port we need to determine whether it supports SSL
my $conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
);
if ( $conn ) {
close( $conn );
$mode = 'SSL';
} else {
$mode = '';
}
return $mode;
}
sub get_mbx_list {
my $dir = shift;
my $mbxs = shift;
my %MBXS;
if ( $mbx_list ) {
# The user has supplied a list of mailboxes.
@$mbxs = split(/,/, $mbx_list );
return;
}
@dirs = ();
push( @dirs, $dir );
@messages = ();
find( \&findMsgs, @dirs ); # Returns @messages
foreach $fn ( @messages ) {
Log("fn = $fn") if $debug;
$fn =~ s/$dir//;
Log("fn = $fn") if $debug;
$i = rindex($fn,'/');
Log("find rightmost slash, i = $i") if $debug;
if ( $fn =~ /^\// ) {
$mbx = substr($fn,1,$i);
} else {
$mbx = substr($fn,0,$i);
}
Log("mbx = $mbx") if $debug;
$mbx =~ s/\/$//;
Log("mbx = >$mbx<") if $debug;
push( @$mbxs, $mbx ) if !$MBXS{"$mbx"};
Log("Add >$mbx< to the list of mailboxes") if $debug;
$MBXS{"$mbx"} = 1;
}
}
sub findMsgs {
return if not -f;
my $fn = $File::Find::name;
push( @messages, $fn );
}
sub namespace {
my $conn = shift;
my $prefix = shift;
my $delimiter = shift;
# Query the server with NAMESPACE so we can determine its
# mailbox prefix (if any) and hierachy delimiter.
@response = ();
sendCommand( $conn, "1 NAMESPACE");
while ( 1 ) {
readResponse( $conn );
if ( $response =~ /^1 OK/i ) {
last;
} elsif ( $response =~ /^1 NO|^1 BAD|^\* BYE/i ) {
Log("Unexpected response to NAMESPACE command: $response");
Log("Cannot determine the mailbox delimiter and prefix. Use -y '<delimiter prefix>' to supply it");
exit;
}
}
foreach $_ ( @response ) {
if ( /NAMESPACE/i ) {
my $i = index( $_, '((' );
my $j = index( $_, '))' );
my $val = substr($_,$i+2,$j-$i-3);
($val) = split(/\)/, $val);
($$prefix,$$delimiter) = split( / /, $val );
$$prefix =~ s/"//g;
$$delimiter =~ s/"//g;
# Experimental
if ( $public_mbxs ) {
# Figure out the public mailbox settings
/\(\((.+)\)\)\s+\(\((.+)\s+\(\((.+)\)\)/;
$public = $3;
$public =~ /"(.+)"\s+"(.+)"/;
$src_public_prefix = $1 if $conn eq $src;
$src_public_delim = $2 if $conn eq $src;
$dst_public_prefix = $1 if $conn eq $dst;
$dst_public_delim = $2 if $conn eq $dst;
}
last;
}
last if /^1 NO|^1 BAD|^\* BYE/;
}
unless ( $$delimiter ) {
# NAMESPACE command is not supported by the server
# so we will have to figure it out another way.
$delim = getDelimiter( $conn );
$$delimiter = $delim;
$$prefix = '';
}
if ( $debug ) {
Log("prefix >$$prefix<");
Log("delim >$$delimiter<");
}
}
sub mailboxName {
my $srcmbx = shift;
my $srcPrefix = shift;
my $srcDelim = shift;
my $dstPrefix = shift;
my $dstDelim = shift;
my $dstmbx;
my $substChar = '_';
if ( $public_mbxs ) {
my ($public_src,$public_dst) = split(/:/, $public_mbxs );
# If the mailbox starts with the public mailbox prefix then
# map it to the public mailbox destination prefix
if ( $srcmbx =~ /^$public_src/ ) {
Log("src: $srcmbx is a public mailbox") if $debug;
$dstmbx = $srcmbx;
$dstmbx =~ s/$public_src/$public_dst/;
Log("dst: $dstmbx") if $debug;
return $dstmbx;
}
}
# Change the mailbox name if the user has supplied mapping rules.
if ( $mbx_map{"$srcmbx"} ) {
$srcmbx = $mbx_map{"$srcmbx"}
}
# Adjust the mailbox name if the source and destination server
# have different mailbox prefixes or hierarchy delimiters.
if ( ($srcmbx =~ /[$dstDelim]/) and ($dstDelim ne $srcDelim) ) {
# The mailbox name has a character that is used on the destination
# as a mailbox hierarchy delimiter. We have to replace it.
$srcmbx =~ s^[$dstDelim]^$substChar^g;
}
if ( $debug ) {
Log("src mbx $srcmbx");
Log("src prefix $srcPrefix");
Log("src delim $srcDelim");
Log("dst prefix $dstPrefix");
Log("dst delim $dstDelim");
}
$srcmbx =~ s/^$srcPrefix//;
$srcmbx =~ s/\\$srcDelim/\//g;
if ( ($srcPrefix eq $dstPrefix) and ($srcDelim eq $dstDelim) ) {
# No adjustments necessary
# $dstmbx = $srcmbx;
if ( lc( $srcmbx ) eq 'inbox' ) {
$dstmbx = $srcmbx;
} else {
$dstmbx = $srcPrefix . $srcmbx;
}
if ( $root_mbx ) {
# Put folders under a 'root' folder on the dst
$dstmbx =~ s/^$dstPrefix//;
$dstDelim =~ s/\./\\./g;
$dstmbx =~ s/^$dstDelim//;
$dstmbx = $dstPrefix . $root_mbx . $dstDelim . $dstmbx;
if ( uc($srcmbx) eq 'INBOX' ) {
# Special case for the INBOX
$dstmbx =~ s/INBOX$//i;
$dstmbx =~ s/$dstDelim$//;
}
$dstmbx =~ s/\\//g;
}
return $dstmbx;
}
$srcmbx =~ s#^$srcPrefix##;
$dstmbx = $srcmbx;
if ( $srcDelim ne $dstDelim ) {
# Need to substitute the dst's hierarchy delimiter for the src's one
$srcDelim = '\\' . $srcDelim if $srcDelim eq '.';
$dstDelim = "\\" . $dstDelim if $dstDelim eq '.';
$dstmbx =~ s#$srcDelim#$dstDelim#g;
$dstmbx =~ s/\\//g;
}
if ( $srcPrefix ne $dstPrefix ) {
# Replace the source prefix with the dest prefix
$dstmbx =~ s#^$srcPrefix## if $srcPrefix;
if ( $dstPrefix ) {
$dstmbx = "$dstPrefix$dstmbx" unless uc($srcmbx) eq 'INBOX';
}
$dstDelim = "\\$dstDelim" if $dstDelim eq '.';
$dstmbx =~ s#^$dstDelim##;
}
if ( $root_mbx ) {
# Put folders under a 'root' folder on the dst
$dstDelim =~ s/\./\\./g;
$dstmbx =~ s/^$dstPrefix//;
$dstmbx =~ s/^$dstDelim//;
$dstmbx = $dstPrefix . $root_mbx . $dstDelim . $dstmbx;
if ( uc($srcmbx) eq 'INBOX' ) {
# Special case for the INBOX
$dstmbx =~ s/INBOX$//i;
$dstmbx =~ s/$dstDelim$//;
}
$dstmbx =~ s/\\//g;
}
return $dstmbx;
}
sub getDelimiter {
my $conn = shift;
my $delimiter;
# Issue a 'LIST "" ""' command to find out what the
# mailbox hierarchy delimiter is.
sendCommand ($conn, '1 LIST "" ""');
@response = '';
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
return 0;
}
}
for $i (0 .. $#response) {
$response[$i] =~ s/\s+/ /;
if ( $response[$i] =~ /\* LIST \((.*)\) "(.*)" "(.*)"/i ) {
$delimiter = $2;
}
}
return $delimiter;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 953 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 884 B

View File

@ -1,502 +0,0 @@
#!/usr/bin/perl
# $Header: /mhub4/sources/imap-tools/imapCapability.pl,v 1.9 2014/10/15 21:42:58 rick Exp $
###########################################################################
# Program name imapCapability.pl #
# Written by Rick Sanders #
# Date 23 December 2007 #
# #
# Description #
# #
# imapCapability.pl is a simple program for querying an IMAP #
# server for a list of the IMAP features it supports. #
# #
# Description #
# #
# imapCapability is used to discover what services an IMAP #
# server supports. #
# #
# Usage: imapCapability.pl -h <host> -u <user> -p <password> #
# Optional arguments: -d (debug) -m (list folders) #
# #
# Sample output: #
# The server supports the following IMAP capabilities: #
# #
# IMAP4 IMAP4REV1 ACL NAMESPACE UIDPLUS IDLE LITERAL+ QUOTA #
# ID MULTIAPPEND LISTEXT CHILDREN BINARY LOGIN-REFERRALS #
# UNSELECT STARTTLS AUTH=LOGIN AUTH=PLAIN AUTH=CRAM-MD5 #
# AUTH=DIGEST-MD5 AUTH=GSSAPI AUTH=MSN AUTH=NTLM #
###########################################################################
############################################################################
# Copyright (c) 2012 Rick Sanders <rfs9999@earthlink.net> #
# #
# Permission to use, copy, modify, and distribute this software for any #
# purpose with or without fee is hereby granted, provided that the above #
# copyright notice and this permission notice appear in all copies. #
# #
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES #
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR #
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES #
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN #
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF #
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #
############################################################################
use Socket;
use FileHandle;
use Fcntl;
use Getopt::Std;
use IO::Socket;
eval 'use Encode qw/encode decode/';
eval 'use Encode::IMAPUTF7 qw/encode decode/';
use MIME::Base64 qw(encode_base64 decode_base64);
#################################################################
# Main program. #
#################################################################
($host,$user,$pwd) = getArgs();
unless ( $host and $user and $pwd ) {
print "Host:Port > ";
chomp($host = <>);
print "Username > ";
chomp($user = <>);
print "Password > ";
chomp($pwd = <>);
}
unless ( $host and $user and $pwd ) {
print "Please supply host, username, and password\n";
exit;
}
init();
connectToHost($host, \$conn) or exit;
login($user,$pwd, $conn) or exit;
capability( $conn );
if ( $list_mbxs ) {
print STDOUT "\nList of mailboxes for $user:\n\n";
@mbxs = listMailboxes( $conn );
foreach $mbx ( @mbxs ) {
$mbx1 = decode( 'IMAP-UTF-7', $mbx );
if ( $mbx eq $mbx1 ) {
print STDOUT " $mbx\n";
} elsif( $utf7_installed ) {
print STDOUT " $mbx ($mbx1)\n";
} else {
print STDOUT " $mbx\n";
}
}
}
logout( $conn );
sub init {
# Determine whether we have SSL support via openSSL and IO::Socket::SSL
$ssl_installed = 1;
eval 'use IO::Socket::SSL';
if ( $@ ) {
$ssl_installed = 0;
}
$utf7_installed = 1;
eval 'use Encode::IMAPUTF7 qw/decode/';
if ( $@ ) {
$utf7_installed = 0;
}
}
sub getArgs {
getopts( "h:u:p:dmA:I" );
$host = $opt_h;
$user = $opt_u;
$pwd = $opt_p;
$debug = $opt_d;
$admin_user = $opt_A;
$list_mbxs = 1 if $opt_m;
$showIMAP = 1 if $opt_I;
if ( $admin_user ) {
# Don't need user password
$pwd = 'XXXX';
}
if ( $opt_H ) {
usage();
}
if ( !$host or !$user or !$pwd ) {
usage();
}
return ($host,$user,$pwd);
}
sub usage {
print STDOUT "usage: imapCapability.pl -h <host> -u <user> -p <password>\n";
print STDOUT " Option argument: -m (list mailboxes)\n";
exit;
}
sub connectToHost {
my $host = shift;
my $conn = shift;
($host,$port) = split(/:/, $host);
$port = 143 unless $port;
# We know whether to use SSL for ports 143 and 993. For any
# other ones we'll have to figure it out.
$mode = sslmode( $host, $port );
if ( $mode eq 'SSL' ) {
unless( $ssl_installed == 1 ) {
warn("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
exit;
}
print "Attempting an SSL connection\n" if $debug;
$$conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET,
);
unless ( $$conn ) {
$error = IO::Socket::SSL::errstr();
print "Error connecting to $host: $error\n";
exit;
}
} else {
# Non-SSL connection
print "Attempting a non-SSL connection\n" if $debug;
$$conn = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
);
unless ( $$conn ) {
print "Error connecting to $host:$port: $@\n";
warn "Error connecting to $host:$port: $@";
exit;
}
}
print "Connected to $host on port $port\n";
}
sub sslmode {
my $host = shift;
my $port = shift;
my $mode;
# Determine whether to make an SSL connection
# to the host. Return 'SSL' if so.
if ( $port == 143 ) {
# Standard non-SSL port
return '';
} elsif ( $port == 993 ) {
# Standard SSL port
return 'SSL';
}
unless ( $ssl_installed ) {
# We don't have SSL installed on this machine
return '';
}
# For any other port we need to determine whether it supports SSL
my $conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
);
if ( $conn ) {
close( $conn );
$mode = 'SSL';
} else {
$mode = '';
}
return $mode;
}
sub login {
my $user = shift;
my $pwd = shift;
my $conn = shift;
if ( $admin_user ) {
# An AUTHENTICATE = PLAIN login has been requested
($authuser,$authpwd) = split(/:/, $admin_user );
login_plain( $user, $authuser, $authpwd, $conn ) or exit;
return 1;
}
if ( $pwd =~ /^oauth2:(.+)/i ) {
$token = $1;
Log("password is an OAUTH2 token");
login_xoauth2( $user, $token, $conn );
return 1;
}
sendCommand ($conn, "1 LOGIN $user $pwd");
while (1) {
readResponse ( $conn );
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD/i) {
print "Unexpected LOGIN response: $response\n";
return 0;
}
}
print "Logged in as $user\n" if $debug;
return 1;
}
# login_plain
#
# login in at the source host with the user's name and password. If provided
# with administrator credential, use them as this eliminates the need for the
# user's password.
#
sub login_plain {
my $user = shift;
my $admin = shift;
my $pwd = shift;
my $conn = shift;
# Do an AUTHENTICATE = PLAIN. If an admin user has been provided then use it.
if ( !$admin ) {
# Log in as the user
$admin = $user
}
$login_str = sprintf("%s\x00%s\x00%s", $user,$admin,$pwd);
$login_str = encode_base64("$login_str", "");
$len = length( $login_str );
# sendCommand ($conn, "1 AUTHENTICATE \"PLAIN\" {$len}" );
sendCommand ($conn, "1 AUTHENTICATE PLAIN" );
my $loops;
while (1) {
readResponse ( $conn );
last if $response =~ /\+/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
sendCommand ($conn, "$login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /Microsoft Exchange/i and $conn eq $dst ) {
# The destination is an Exchange server
$exchange = 1;
Log("The destination is an Exchange server");
}
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
return 1;
}
# login_xoauth2
#
# login in at the source host with the user's name and an XOAUTH2 token.
#
sub login_xoauth2 {
my $user = shift;
my $token = shift;
my $conn = shift;
# Do an AUTHENTICATE = XOAUTH2 login
$login_str = encode_base64("user=". $user ."\x01auth=Bearer ". $token ."\x01\x01", '');
sendCommand ($conn, "1 AUTHENTICATE XOAUTH2 $login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /^\+ (.+)/ ) {
$error = decode_base64( $1 );
Log("XOAUTH authentication as $user failed: $error");
return 0;
}
last if $response =~ /^1 OK/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE|failed/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
$last if $loops++ > 5;
}
Log("login complete") if $debug;
return 1;
}
sub capability {
my $conn = shift;
my @response;
my $capability;
sendCommand ($conn, "1 CAPABILITY");
while (1) {
readResponse ( $conn );
$capability = $response if $response =~ /\* CAPABILITY/i;
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD/i) {
print "Unexpected response: $response\n";
return 0;
}
}
print STDOUT "\nThe server supports the following IMAP capabilities:\n\n";
$capability =~ s/^\* CAPABILITY //;
print "$capability\n";
}
sub logout {
my $conn = shift;
undef @response;
sendCommand ($conn, "1 LOGOUT");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
print "Unexpected LOGOUT response: $response\n";
last;
}
}
close $conn;
return;
}
sub sendCommand {
my $fd = shift;
my $cmd = shift;
print $fd "$cmd\r\n";
print STDOUT "$cmd\n" if $showIMAP;
}
sub readResponse {
my $fd = shift;
$response = <$fd>;
chop $response;
$response =~ s/\r//g;
push (@response,$response);
print STDOUT "$response\n" if $showIMAP;
}
# listMailboxes
#
# Get a list of the user's mailboxes
#
sub listMailboxes {
my $conn = shift;
sendCommand ($conn, "1 LIST \"\" *");
undef @response;
while ( 1 ) {
&readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
&Log ("unexpected response: $response");
return 0;
}
}
@mbxs = ();
for $i (0 .. $#response) {
$response[$i] =~ s/\s+/ /;
if ( $response[$i] =~ /"$/ ) {
$response[$i] =~ /\* LIST \((.*)\) "(.+)" "(.+)"/i;
$mbx = $3;
} elsif ( $response[$i] =~ /\* LIST \((.*)\) NIL (.+)/i ) {
$mbx = $2;
} else {
$response[$i] =~ /\* LIST \((.*)\) "(.+)" (.+)/i;
$mbx = $3;
}
$mbx =~ s/^\s+//; $mbx =~ s/\s+$//;
push ( @mbxs, $mbx ) if $mbx ne '';
}
return @mbxs;
}
sub isAscii {
my $str = shift;
my $ascii = 1;
# Determine whether a string contains non-ASCII characters
my $test = $str;
$test=~s/\P{IsASCII}/?/g;
$ascii = 0 unless $test eq $str;
return $ascii;
}
sub Log {
my $str = shift;
print STDERR "$str\n";
}

View File

@ -1,488 +0,0 @@
#!/usr/bin/perl
# $Header: /mhub4/sources/imap-tools/imapPing.pl,v 1.3 2013/09/30 14:27:38 rick Exp $
############################################################################
# Program imapPing.pl #
# Date 20 January 2008 #
# #
# Description #
# #
# This script performs some basic IMAP operations on a user's #
# account and displays the time as each one is executed. The #
# operations are: #
# 1. Connect to the IMAP server #
# 2. Log in with the user's name and password #
# 3. Get a list of mailboxes in the user's account #
# 4. Select the INBOX #
# 5. Get a list of messages in the INBOX #
# 6. Log off the server #
# #
# Usage: imapPing.pl -h <host> -u <user> -p <password> #
# #
############################################################################
# Copyright (c) 2008 Rick Sanders <rfs9999@earthlink.net> #
# #
# Permission to use, copy, modify, and distribute this software for any #
# purpose with or without fee is hereby granted, provided that the above #
# copyright notice and this permission notice appear in all copies. #
# #
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES #
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR #
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES #
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN #
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF #
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #
############################################################################
use Getopt::Std;
use Socket;
use FileHandle;
use Fcntl;
use IO::Socket;
use MIME::Base64 qw(encode_base64);
init();
($host,$user,$pwd) = getArgs();
print STDOUT pack( "A35 A10", "Connecting to $host", getTime() );
connectToHost( $host, \$conn );
print STDOUT pack( "A35 A10","Logging in as $user", getTime() );
login( $user,$pwd, $conn );
print STDOUT pack( "A35 A10","Get list of mailboxes", getTime() );
getMailboxList( $conn );
print STDOUT pack( "A35 A10","Selecting the INBOX", getTime() );
selectMbx( 'INBOX', $conn ) if $rc;
print STDOUT pack( "A35 A10","Get list of msgs in INBOX", getTime() );
getMsgList( 'INBOX', $conn );
print STDOUT pack( "A35 A10","Logging out", getTime() );
logout( $conn );
print STDOUT pack( "A35 A10","Done", getTime() );
exit;
exit 1;
sub init {
# Determine whether we have SSL support via openSSL and IO::Socket::SSL
$ssl_installed = 1;
eval 'use IO::Socket::SSL';
if ( $@ ) {
$ssl_installed = 0;
}
getTime();
$debug = 1;
}
sub getTime {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
if ($year < 99) { $yr = 2000; }
else { $yr = 1900; }
$date = sprintf ("%.2d-%.2d-%d.%.2d:%.2d:%.2d \n",
$mon+1,$mday,$year+$yr,$hour,$min,$sec);
$time = sprintf ("%.2d:%.2d:%.2d \n",$hour,$min,$sec);
return $time;
}
sub getArgs {
getopts( "h:u:p:A:" );
$host = $opt_h;
$user = $opt_u;
$pwd = $opt_p;
$admin_user = $opt_A;
$showIMAP = 1 if $opt_I;
if ( $opt_H ) {
usage();
}
if ( $admin_user ) {
$pwd = 'XXX'; # Don't need the user's password
}
unless ( $host and $user and $pwd ) {
usage();
exit;
}
return ($host,$user,$pwd);
}
# sendCommand
#
# This subroutine formats and sends an IMAP protocol command to an
# IMAP server on a specified connection.
#
sub sendCommand
{
local($fd) = shift @_;
local($cmd) = shift @_;
print $fd "$cmd\r\n";
print STDOUT ">> $cmd\n" if $showIMAP;
}
#
# readResponse
#
# This subroutine reads and formats an IMAP protocol response from an
# IMAP server on a specified connection.
#
sub readResponse
{
local($fd) = shift @_;
$response = <$fd>;
chop $response;
$response =~ s/\r//g;
push (@response,$response);
print STDOUT "<< $response\n" if $showIMAP;
}
# Make a connection to an IMAP host
sub connectToHost {
my $host = shift;
my $conn = shift;
($host,$port) = split(/:/, $host);
$port = 143 unless $port;
# We know whether to use SSL for ports 143 and 993. For any
# other ones we'll have to figure it out.
$mode = sslmode( $host, $port );
if ( $mode eq 'SSL' ) {
unless( $ssl_installed == 1 ) {
warn("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
exit;
}
$$conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET,
);
unless ( $$conn ) {
$error = IO::Socket::SSL::errstr();
warn("Error connecting to $host: $error");
exit;
}
} else {
# Non-SSL connection
$$conn = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
);
unless ( $$conn ) {
warn "Error connecting to $host:$port: $@";
exit;
}
}
}
sub sslmode {
my $host = shift;
my $port = shift;
my $mode;
# Determine whether to make an SSL connection
# to the host. Return 'SSL' if so.
if ( $port == 143 ) {
# Standard non-SSL port
return '';
} elsif ( $port == 993 ) {
# Standard SSL port
return 'SSL';
}
unless ( $ssl_installed ) {
# We don't have SSL installed on this machine
return '';
}
# For any other port we need to determine whether it supports SSL
my $conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
);
if ( $conn ) {
close( $conn );
$mode = 'SSL';
} else {
$mode = '';
}
return $mode;
}
# login
#
# login in at the source host with the user's name and password
#
sub login {
my $user = shift;
my $pwd = shift;
my $conn = shift;
if ( $admin_user ) {
# An AUTHENTICATE = PLAIN login has been requested
($authuser,$authpwd) = split(/:/, $admin_user );
login_plain( $user, $authuser, $authpwd, $conn ) or exit;
return 1;
}
sendCommand ($conn, "1 LOGIN $user $pwd");
while (1) {
readResponse ($conn);
if ($response =~ /^1 OK/i) {
last;
}
elsif ($response !~ /^\*/) {
print STDOUT "Unexpected login response $response\n";
return 0;
}
}
return 1;
}
# login_plain
#
# login in at the source host with the user's name and password. If provided
# with administrator credential, use them as this eliminates the need for the
# user's password.
#
sub login_plain {
my $user = shift;
my $admin = shift;
my $pwd = shift;
my $conn = shift;
# Do an AUTHENTICATE = PLAIN. If an admin user has been provided then use it.
if ( !$admin ) {
# Log in as the user
$admin = $user
}
$login_str = sprintf("%s\x00%s\x00%s", $user,$admin,$pwd);
$login_str = encode_base64("$login_str", "");
$len = length( $login_str );
# sendCommand ($conn, "1 AUTHENTICATE \"PLAIN\" {$len}" );
sendCommand ($conn, "1 AUTHENTICATE PLAIN" );
my $loops;
while (1) {
readResponse ( $conn );
last if $response =~ /\+/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
sendCommand ($conn, "$login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /Microsoft Exchange/i and $conn eq $dst ) {
# The destination is an Exchange server
$exchange = 1;
Log("The destination is an Exchange server");
}
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
return 1;
}
# logout
#
# log out from the source host
#
sub logout {
my $conn = shift;
# print STDOUT "Logging out\n" if $debug;
sendCommand ($conn, "1 LOGOUT");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
print STDOUT "unexpected LOGOUT response: $response\n";
last;
}
}
close $conn;
return;
}
sub usage {
print STDOUT "\nUsage: imapPing.pl <args> \n\n";
print STDOUT " -h <hostname>\n";
print STDOUT " -u <user>\n";
print STDOUT " -p <password>\n";
exit;
}
sub selectInbox {
my $mbx = shift;
my $conn = shift;
# Select a mailbox
sendCommand ($conn, "1 SELECT $mbx");
while (1) {
readResponse ($conn);
if ($response =~ /^1 OK/i) {
last;
}
elsif ($response !~ /^\*/) {
print STDOUT "Unexpected SELECT INBOX response: $response\n";
return 0;
}
}
}
sub getMailboxList {
my $conn = shift;
# Get a list of the user's mailboxes
sendCommand ($conn, "1 LIST \"\" *");
@response = ();
while ( 1 ) {
readResponse ($conn);
last if $response =~ /^1 OK/i;
if ( $response !~ /^\*/ ) {
print STDOUT "unexpected response: $response\n";
return 0;
}
}
@mbxs = ();
for $i (0 .. $#response) {
# print STDERR "$response[$i]\n";
$response[$i] =~ s/\s+/ /;
($dmy,$mbx) = split(/"\/"/,$response[$i]);
$mbx =~ s/^\s+//; $mbx =~ s/\s+$//;
$mbx =~ s/"//g;
if ($mbx =~ /^\#/) {
# Skip public mbxs
next;
}
if ($mbx ne '') {
push(@mbxs,$mbx);
}
}
return 1;
}
sub getMsgList {
my $mailbox = shift;
my $conn = shift;
# Select the mailbox in read-only mode
sendCommand ($conn, "1 EXAMINE \"$mailbox\"");
undef @response;
$empty=0;
while ( 1 ) {
readResponse ($conn);
last if $response =~ /^1 OK/i;
if ( $response !~ /^\*/ ) {
print STDOUT "Error: $response\n";
return 0;
}
}
sendCommand ($conn, "1 FETCH 1:* (UID FLAGS)");
undef @response;
while ( 1 ) {
readResponse ($conn);
last if $response =~ /^1 OK/i;
if ( $response !~ /^\*/ ) {
print STDOUT "Unexpected response: $response\n";
return 0;
}
}
# Get a list of the msgs in the mailbox
#
undef @msgs;
for $i (0 .. $#response) {
$_ = $response[$i];
$_ =~ /\* ([^FETCH]*)/;
$uid = $1;
$uid =~ s/\s+$//;
if ($response[$i] =~ /\\Seen/) { $seen = 1; }
if (($uid ne 'OK') && ($uid ne '')) {
push (@msgs,"$uid $seen");
}
}
return 1;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
LOGFILE: imapcopy.log
IMAPCOPY: imapcopy.pl
PROCESS_LIMIT: 8
DEBUG: 0
SHOWIMAP: 0

View File

@ -1,598 +0,0 @@
#!/usr/bin/perl
# $Header: /mhub4/sources/imap-tools/imapcopy.cgi,v 1.9 2014/08/18 15:17:22 rick Exp $
#######################################################################
# Program name imapcopy.cgi #
# Written by Rick Sanders #
# #
# Description #
# #
# imapcopy.cgi is used to manage the imapcopy.pl script in CGI #
# mode. #
#######################################################################
use Socket;
use FileHandle;
use Fcntl;
use Getopt::Std;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use IO::Socket;
use POSIX 'setsid';
use Cwd;
init();
get_html();
# Check the source and dest logins in case the user has provided
# invalid credentials or host names
test_logins();
# To prevent someone from seeing the passwords in ps pass them
# as ENV variables.
$ENV{SOURCEPWD} = $sourcePwd;
$ENV{DESTPWD} = $destPwd;
my $cmd = "$imapcopy ";
$cmd .= "-S $sourceHost/$sourceUser/SOURCEPWD ";
$cmd .= "-D $destHost/$destUser/DESTPWD ";
$cmd .= "-I " if $DEFAULTS{'SHOWIMAP'} == 1;
$cmd .= "-d " if $DEFAULTS{'DEBUG'} == 1;
$cmd .= "-L $logfile " if $logfile;
$cmd .= "-m \"$mbxList\" " if $mbxList;
$cmd .= "-e \"$excludeMbxs\" " if $excludeMbxs;
$cmd .= "-a $sent_after " if $sent_after;
$cmd .= "-b $sent_before " if $sent_before;
$cmd .= "-U " if $update;
$cmd .= "$DEFAULTS{ARGUMENTS} " if $DEFAULTS{ARGUMENTS};
launch_daemon( $cmd );
print STDOUT "<b><br>Your copy job has been started. You will be notified when it has completed</b><br>";
exit;
sub init {
$os = $ENV{'OS'};
print "Content-type: text/html\n\n<html>\n";
print '<meta equiv="refresh" content="5">';
print '</head>';
print '<title>IMAP Copy</title>';
print '<body style="background-color:#FFF8C6" bgproperties="fixed" bgcolor="#FFFFFF" text="#000000"
link="#050473" vlink="#6B6AF5" alink="#840000">';
if ( -e "imapcopy.cf" ) {
open(CF, "<imapcopy.cf") or print "Can't open imapcopy.cf: $!";
}
while( <CF> ) {
chomp;
($kw,$value) = split(/\s*:\s*/, $_, 2);
$DEFAULTS{$kw} = $value;
}
close CF;
if ( $DEFAULTS{'IMAPCOPY'} ) {
$imapcopy = $DEFAULTS{'IMAPCOPY'};
} else {
my $here = getcwd;
$imapcopy = "$here/imapcopy.pl";
}
$logfile = $DEFAULTS{'LOGFILE'};
if ( $logfile ) {
if ( !open(LOG, ">> $logfile")) {
print STDOUT "Can't open $logfile: $!\n";
exit;
}
select(LOG); $| = 1;
}
Log("$0 starting");
$count = count_imapcopy_processes();
if ( $DEFAULTS{PROCESS_LIMIT} ) {
exit if $count > $DEFAULTS{PROCESS_LIMIT};
}
# Determine whether we have SSL support via openSSL and IO::Socket::SSL
$ssl_installed = 1;
eval 'use IO::Socket::SSL';
if ( $@ ) {
$ssl_installed = 0;
}
# Set up signal handling
$SIG{'ALRM'} = 'signalHandler';
$SIG{'HUP'} = 'signalHandler';
$SIG{'INT'} = 'signalHandler';
$SIG{'TERM'} = 'signalHandler';
$SIG{'URG'} = 'signalHandler';
}
sub launch_daemon {
my $cmd = shift;
my $parent = $$;
use POSIX 'setsid';
# The purpose of this routine is to launch imapcopy as a grandkid which detaches
# it from the Apache process so that it will not die if the user closes his browser.
print STDOUT "Your copy job has been started. You will be notified when it has completed.";
if ( !defined (my $kid = fork) ) {
print STDOUT "Cannot fork a child process: $!<br>";
Log("Cannot fork: $!");
exit;
}
if ( $kid ) {
exit(0);
} else {
close STDIN;
close STDOUT;
close STDERR;
if ( !setsid ) {
Log("Cannot execute 'setsid', exiting");
exit;
}
umask(0027); # create files with perms -rw-r-----
if ( !chdir '/' ) {
Log("Can't chdir to /: $!");
exit;
}
if ( !(open STDIN, '<', '/dev/null') ) {
Log("Cannot redirect STDIN: $!");
exit;
}
if ( !(open STDOUT, '>', '/dev/null') ) {
Log("Cannot redirect STDOUT: $!");
exit;
}
if ( !(open STDERR, '>>', $logfile) ) {
Log("Cannot redirect STDERR to $logfile: $!");
Log("Check the path and permissions on $logfile");
exit;
}
if ( !defined (my $grandkid = fork) ) {
exit;
} else {
if ( $grandkid != 0 and $$ != $parent ) {
Log("Execute $cmd");
$rc = `$cmd`;
Log("rc = $rc");
}
exit(0);
}
}
}
sub get_html {
my $fields = shift;
my $formData=0;
# Get the HTML form values
#
my $query = new CGI;
$sourceHost = $query->param('sourceHost');
$sourceUser = $query->param('sourceUser');
$sourcePwd = $query->param('sourcePwd');
$destHost = $query->param('destHost');
$destUser = $query->param('destUser');
$destPwd = $query->param('destPwd');
$mbxList = $query->param('mbxList');
$excludeMbxs = $query->param('excludeMbxList');
$sent_after = $query->param('sent_after');
$sent_before = $query->param('sent_before');
$update = $query->param('update');
$update = 1 if $update eq 'on';
}
sub Log {
my $str = shift;
if ( $logfile ) {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
if ($year < 99) { $yr = 2000; }
else { $yr = 1900; }
$line = sprintf ("%.2d-%.2d-%d.%.2d:%.2d:%.2d %s\n",
$mon + 1, $mday, $year + $yr, $hour, $min, $sec,$str);
print LOG "$line";
}
}
# login
#
# login in at the source host with the user's name and password
#
sub login {
my $user = shift;
my $pwd = shift;
my $host = shift;
my $conn = shift;
my $method = shift;
Log("method $method") if $debug;
return 1 if $method eq 'PREAUTH'; # Server pre-authenticates users
Log("Authenticating to $host as $user");
if ( uc( $method ) eq 'CRAM-MD5' ) {
# A CRAM-MD5 login is requested
Log("login method $method");
my $rc = login_cram_md5( $user, $pwd, $conn );
return $rc;
}
if ( $user =~ /(.+):(.+)/ ) {
# An AUTHENTICATE = PLAIN login has been requested
$sourceUser = $1;
$authuser = $2;
login_plain( $sourceUser, $authuser, $pwd, $conn ) or exit;
return 1;
}
# Otherwise do an ordinary login
sendCommand ($conn, "1 LOGIN $user \"$pwd\"");
while (1) {
readResponse ( $conn );
if ( $response =~ /Cyrus/i and $conn eq $dst ) {
Log("Destination is a Cyrus server");
$cyrus = 1;
}
if ( $response =~ /Microsoft Exchange/i and $conn eq $dst ) {
# The destination is an Exchange server
unless ( $exchange_override ) {
$exchange = 1;
Log("The destination is an Exchange server");
}
}
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
}
Log("Logged in as $user") if $debug;
return 1;
}
sub login_cram_md5 {
my $user = shift;
my $pwd = shift;
my $conn = shift;
sendCommand ($conn, "1 AUTHENTICATE CRAM-MD5");
while (1) {
readResponse ( $conn );
last if $response =~ /^\+/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
}
my ($challenge) = $response =~ /^\+ (.+)/;
Log("challenge $challenge") if $debug;
$response = cram_md5( $challenge, $user, $pwd );
Log("response $response") if $debug;
sendCommand ($conn, $response);
while (1) {
readResponse ( $conn );
if ( $response =~ /Microsoft Exchange/i and $conn eq $dst ) {
# The destination is an Exchange server
$exchange = 1;
Log("The destination is an Exchange server");
}
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
}
Log("Logged in as $user") if $debug;
return 1;
}
# login_plain
#
# login in at the source host with the user's name and password. If provided
# with administrator credential, use them as this eliminates the need for the
# user's password.
#
sub login_plain {
my $user = shift;
my $admin = shift;
my $pwd = shift;
my $conn = shift;
# Do an AUTHENTICATE = PLAIN. If an admin user has been provided then use it.
if ( !$admin ) {
# Log in as the user
$admin = $user
}
$login_str = sprintf("%s\x00%s\x00%s", $user,$admin,$pwd);
$login_str = encode_base64("$login_str", "");
$len = length( $login_str );
# sendCommand ($conn, "1 AUTHENTICATE \"PLAIN\" {$len}" );
sendCommand ($conn, "1 AUTHENTICATE PLAIN" );
my $loops;
while (1) {
readResponse ( $conn );
last if $response =~ /\+/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
sendCommand ($conn, "$login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /Cyrus/i and $conn eq $dst ) {
Log("Destination is a Cyrus server");
$cyrus = 1;
}
if ( $response =~ /Microsoft Exchange/i and $conn eq $dst ) {
# The destination is an Exchange server
$exchange = 1;
Log("The destination is an Exchange server");
}
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
return 1;
}
# logout
#
# log out from the host
#
sub logout {
my $conn = shift;
undef @response;
sendCommand ($conn, "1 LOGOUT");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected LOGOUT response: $response");
last;
}
}
close $conn;
return;
}
# Make a connection to a IMAP host
sub connectToHost {
my $host = shift;
my $conn = shift;
Log("Connecting to $host") if $debug;
($host,$port) = split(/:/, $host);
$port = 143 unless $port;
# We know whether to use SSL for ports 143 and 993. For any
# other ones we'll have to figure it out.
$mode = sslmode( $host, $port );
if ( $mode eq 'SSL' ) {
unless( $ssl_installed == 1 ) {
warn("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
Log("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
exit;
}
Log("Attempting an SSL connection") if $debug;
$$conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET,
Timeout => 10,
);
unless ( $$conn ) {
$error = IO::Socket::SSL::errstr();
Log("Error connecting to $host: $error");
print STDOUT "<font color=red><b>Error: Can't connect to $host.<br>";
print STDOUT "Hit the Back button on your browser, correct the info, and try again.";
exit;
}
} else {
# Non-SSL connection
Log("Attempting a non-SSL connection") if $debug;
$$conn = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
Timeout => 10,
);
unless ( $$conn ) {
Log("Error connecting to $host:$port: $@");
print STDOUT "<font color=red><b>Error: Can't connect to $host.<br>";
print STDOUT "Hit the Back button on your browser, correct the info, and try again.";
exit;
}
}
Log("Connected to $host on port $port");
}
sub sslmode {
my $host = shift;
my $port = shift;
my $mode;
# Determine whether to make an SSL connection
# to the host. Return 'SSL' if so.
if ( $port == 143 ) {
# Standard non-SSL port
return '';
} elsif ( $port == 993 ) {
# Standard SSL port
return 'SSL';
}
unless ( $ssl_installed ) {
# We don't have SSL installed on this machine
return '';
}
# For any other port we need to determine whether it supports SSL
my $conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
);
if ( $conn ) {
close( $conn );
$mode = 'SSL';
} else {
$mode = '';
}
return $mode;
}
sub test_logins {
# Verify that we can log in at the source and destination before launching
# the copy job.
print "<br><br>";
if ( !connectToHost($sourceHost, \$src) ) {
print STDOUT "<font color=red> <b>Error: Can't connect to $sourceHost. Check that $sourceHost is correct.<br>";
print STDOUT "Hit the Back button on your browser, correct the info, and try again.";
exit;
}
if ( !login($sourceUser,$sourcePwd, $sourceHost, $src, $srcMethod) ) {
print STDOUT "<font color=red><b>Error: Can't login as $sourceUser. Check your username and password<br>";
print STDOUT "Hit the Back button on your browser, correct the info, and try again.";
exit;
}
if ( !connectToHost($destHost, \$dst) ) {
print STDOUT "<font color=red><b>Error: Can't connect to $destHost. Check that $destHost is correct.\n";
print STDOUT "Hit the Back button on your browser, correct the info, and try again.";
exit;
}
if ( !login($destUser,$destPwd, $destHost, $dst, $dstMethod) ) {
print STDOUT "<font color=red><b>Error: Can't login as $destUser. Check your username and password<br>";
print STDOUT "Hit the Back button on your browser, correct the info, and try again.";
exit;
}
}
sub sendCommand {
my $fd = shift;
my $cmd = shift;
print $fd "$cmd\r\n";
Log (">> $cmd") if $showIMAP;
}
#
# readResponse
#
# This subroutine reads and formats an IMAP protocol response from an
# IMAP server on a specified connection.
#
sub readResponse {
my $fd = shift;
$response = <$fd>;
chop $response;
$response =~ s/\r//g;
push (@response,$response);
Log ("<< $response") if $showIMAP;
}
sub count_imapcopy_processes {
my $count;
# Count how many imapcopy processes are currently running
# and exit if the max has been reached.
foreach $_ ( `ps -ef | grep imapcopy.pl` ) {
next unless /imapcopy.pl/;
next if /grep/;
$count++;
}
$process_limit = $DEFAULTS{PROCESS_LIMIT};
if ( $process_limit > 0 and $count > $process_limit ) {
print STDOUT "<br><br><b>The maximum number of IMAP copies is already running. Please try again later.<br>";
}
return $count;
}

View File

@ -1,86 +0,0 @@
<html>
<title>IMAPCOPY</title>
<head>
<FORM name="imapcopy" method=post action="../cgi-bin/imapcopy.cgi" ENCTYPE="multipart/form-data">
<script language="javascript">
var pageLoaded = false;
function validate() {
if ( !document.imapcopy.sourceHost.value ||
!document.imapcopy.sourceUser.value ||
!document.imapcopy.sourcePwd.value ||
!document.imapcopy.destHost.value ||
!document.imapcopy.destUser.value ||
!document.imapcopy.destPwd.value
) {
alert("Please enter values for source & destination servers, source & destination usernames, and source & destination passwords");
return false;
} else {
return true;
}
}
</script>
</head>
<body style="background-color:#FFF8C6" bgproperties="fixed" bgcolor="#FFFFFF" text="#000000"
link="#050473" vlink="#6B6AF5" alink="#840000">
<H3><font size=6 color="#0000ff"> IMAPCOPY</font></H3>
<br>
<table>
<tr>
<td>Source server
<td><input type=text name=sourceHost value=SOURCEHOST>
<tr>
<td>Destination server
<td><input type=text name=destHost value=DESTHOST>
<tr>
<td>Source username <td><input type=text name=sourceUser>
<td>Source password <td><input type=password name=sourcePwd>
<tr>
<td>Destination username <td><input type=text name=destUser>
<td>Destination password <td><input type=password name=destPwd>
</table>
<br><br>
<table>
<tr>
<td>Copy only these folders
<td><input type=text name="mbxList" size=35> folder1,folder2,...
<tr>
<td>Exclude these folders
<td><input type=text name="excludeMbxList" size=35> folder1,folder2,...
<tr>
<td>After date
<td><input type=text name=sent_after> DD-MMM-YYYY
<tr>
<td>Before Date
<td><input type=text name=sent_before> DD-MMM-YYYY
<tr>
<td>Update Mode
<td><input type=checkbox name=update><br>
</table>
<br><br>
<input type=submit value="Submit" onclick="return validate()">
<input type=reset value="Clear form">
<br><br>
After clicking on Submit the copy process will start.
Depending on the size of your
account it will take a few minutes or more to copy everything over.
When it finishes you will receive an e-mail notifying of the results.
</form>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,86 +0,0 @@
<html>
<title>IMAPCOPY</title>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<FORM name="imapcopy" method=post action="imapcopy.cgi" ENCTYPE="multipart/form-data">
<script language="javascript">
var pageLoaded = false;
function validate() {
if ( !document.imapcopy.sourceHost.value ||
!document.imapcopy.sourceUser.value ||
!document.imapcopy.sourcePwd.value ||
!document.imapcopy.destHost.value ||
!document.imapcopy.destUser.value ||
!document.imapcopy.destPwd.value
) {
alert("Please enter values for source & destination servers, source & destination usernames, and source & destination passwords");
return false;
} else {
return true;
}
}
</script>
</head>
<body style="background-color:#FFF8C6" bgproperties="fixed" bgcolor="#FFFFFF" text="#000000"
link="#050473" vlink="#6B6AF5" alink="#840000">
<H3><font size=6 color="#0000ff"> IMAPCOPY</font></H3>
<p>
<a href="imapcopy_en.html"><img src="flag_en.gif" width="50" height="38" border="0" alt="EN"></a>
<a href="imapcopy_de.html"><img src="flag_de.gif" width="50" height="38" border="0" alt="DE"></a>
</p>
<br>
<table>
<tr>
<td>Quellserver:
<td><input type=text name=sourceHost value=imap.quellserver.de>
<tr>
<td>Zielserver:
<td><input type=text name=destHost value=imap.zielserver.de>
<tr>
<td>Benutzername Quellserver:<td><input type=text name=sourceUser>
<td>Passwort Quellserver:<td><input type=password name=sourcePwd>
<tr>
<td>Benutzername Zielserver:<td><input type=text name=destUser>
<td>Passwort Zielserver:<td><input type=password name=destPwd>
</table>
<br><br>
<table>
<tr>
<td>Nur diese Ordner kopieren:
<td><input type=text name="mbxList" size=35> Ordner1,Ordner2, ...
<tr>
<td>Diese Ordner nicht kopieren:
<td><input type=text name="excludeMbxList" size=35> Ordner1,Ordner2, ...
<tr>
<td>Nachrichten kopieren nach Datum
<td><input type=text name=sent_after> TT-MMM-JJJJ
<tr>
<td>Nachrichten kopieren vor Datum
<td><input type=text name=sent_before> TT-MMM-JJJJ
<tr>
<td>Update Mode <br> (nur noch nicht kopierte Nachrichten)
<td><input type=checkbox name=update><br>
</table>
<br><br>
<input type=submit value="Start imapcopy" onclick="return validate()">
<input type=reset value="Formular löschen">
<br><br>
Nach Start imapcopy wird der Kopierprozess gestartet. Abhängig von der Größe der zu kopierenden Accounts kann es einige Minuten oder länger dauern bis alle Nachrichten kopiert sind. Am Ende des Kopierprozesses erhalten Sie eine Nachricht per E-Mail.
</form>
</body>
</html>

View File

@ -1,91 +0,0 @@
<html>
<title>IMAPCOPY</title>
<head>
<FORM name="imapcopy" method=post action="../cgi-bin/imapcopy.cgi" ENCTYPE="multipart/form-data">
<script language="javascript">
var pageLoaded = false;
function validate() {
if ( !document.imapcopy.sourceHost.value ||
!document.imapcopy.sourceUser.value ||
!document.imapcopy.sourcePwd.value ||
!document.imapcopy.destHost.value ||
!document.imapcopy.destUser.value ||
!document.imapcopy.destPwd.value
) {
alert("Please enter values for source & destination servers, source & destination usernames, and source & destination passwords");
return false;
} else {
return true;
}
}
</script>
</head>
<body style="background-color:#FFF8C6" bgproperties="fixed" bgcolor="#FFFFFF" text="#000000"
link="#050473" vlink="#6B6AF5" alink="#840000">
<H3><font size=6 color="#0000ff"> IMAPCOPY</font></H3>
<p>
<a href="imapcopy_en.html"><img src="flag_en.gif" width="50" height="38" border="0" alt="EN"></a>
<a href="imapcopy_de.html"><img src="flag_de.gif" width="50" height="38" border="0" alt="DE"></a>
</p>
<br>
<table>
<tr>
<td>Source server
<td><input type=text name=sourceHost value=SOURCEHOST>
<tr>
<td>Destination server
<td><input type=text name=destHost value=DESTHOST>
<tr>
<td>Source username <td><input type=text name=sourceUser>
<td>Source password <td><input type=password name=sourcePwd>
<tr>
<td>Destination username <td><input type=text name=destUser>
<td>Destination password <td><input type=password name=destPwd>
</table>
<br><br>
<table>
<tr>
<td>Copy only these folders
<td><input type=text name="mbxList" size=35> folder1,folder2,...
<tr>
<td>Exclude these folders
<td><input type=text name="excludeMbxList" size=35> folder1,folder2,...
<tr>
<td>After date
<td><input type=text name=sent_after> DD-MMM-YYYY
<tr>
<td>Before Date
<td><input type=text name=sent_before> DD-MMM-YYYY
<tr>
<td>Update Mode
<td><input type=checkbox name=update><br>
</table>
<br><br>
<input type=submit value="Submit" onclick="return validate()">
<input type=reset value="Clear form">
<br><br>
After clicking on Submit the copy process will start.
Depending on the size of your
account it will take a few minutes or more to copy everything over.
When it finishes you will receive an e-mail notifying of the results.
</form>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
############################################################################
# Copyright (c) 2012 Rick Sanders <rfs9999@earthlink.net> #
# #
# Permission to use, copy, and modify this software for any purpose #
# is hereby granted, provided that the above copyright notice and this #
# permission notice appear in all copies. #
# #
# This software is not assignable and may not be resold without the #
# express written permission of the author. The sofware can be hosted #
# on any or all of the license holder's servers and sites. #
# #
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES #
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR #
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES #
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN #
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF #
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #
############################################################################

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,749 +0,0 @@
#!/usr/bin/perl
use Socket;
use FileHandle;
use Fcntl;
use Getopt::Std;
use MIME::Base64 qw(encode_base64 decode_base64);
######################################################################
# Program name mbxIMAPsync.pl #
# Written by Rick Sanders #
# Date 12 Feb 2004 #
# #
# Description #
# #
# mbxIMAPsync is used to synchronize the contents of a Unix #
# mailfiles with an IMAP mailbox. The user supplies the location #
# & name of the Unix mailbox (eg /var/mail/rfs) and the hostname, #
# username, & password of the IMAP account along with the name #
# of the IMAP mailbox. For example: #
# #
# ./mbxIMAPsync.pl -f /var/mail/rfs -i imapsrv/rfs/mypass -m INBOX #
# #
# mbxIMAPsync compares the messages in the mailfile with those in #
# the IMAP mailbox by Message-Id and adds the ones in the mailfile #
# which are not in the IMAP mailbox. Then it looks for messages #
# in the IMAP mailbox which are not in the mailfile and removes #
# them from the IMAP mailbox. #
# #
# See the Usage() for available options. #
######################################################################
init();
connectToHost($imapHost, \$conn );
login($imapUser,$imapPwd, $conn );
# Get list of msgs in the mailfile by Message-Id
$added=$purged=0;
print STDOUT "Processing $mailfile\n";
print STDOUT "Checking for messages to add\n";
@msgs = readMbox( $mailfile );
foreach $msg ( @msgs ) {
@msgid = grep( /^Message-ID:/i, @$msg );
($label,$msgid) = split(/:/, $msgid[0]);
chomp $msgid;
trim( *msgid );
$mailfileMsgs{"$msgid"} = '1';
push( @sourceMsgs, $msgid );
if ( !findMsg( $msgid, $mbx, $conn ) ) {
# print STDOUT "Need to add msgid >$msgid<\n";
my $message;
foreach $_ ( @$msg ) { chop $_; $message .= "$_\r\n"; }
if ( insertMsg($mbx, \$message, $flags, $date, $conn ) ) {
$added++;
print STDOUT " Added $msgid\n";
}
}
}
# Remove any messages from the IMAP mailbox that no longer
# exist in the mailfile
print STDOUT "Checking for messages to purge\n";
getMsgList( $mbx, \@imapMsgs, $conn );
foreach $msgid ( @imapMsgs ) {
if ( $mailfileMsgs{"$msgid"} eq '' ) {
if ( deleteMsg($msgid, $mbx, $conn ) ) {
Log(" Marked $msgid for deletion");
print STDOUT " Marked msgid $msgid for deletion\n";
$deleted++;
}
}
}
if ( $deleted ) {
# Need to purge the deleted messages
$purged = expungeMbx( $mbx, $conn );
}
Log("Done");
Log("Added $added messages to IMAP mailbox $mbx");
Log("Purged $purged messages from IMAP mailbox $mbx");
print STDOUT "\nAdded $added messages to IMAP mailbox $mbx\n";
print STDOUT "Purged $purged messages from IMAP mailbox $mbx\n";
exit;
sub init {
if ( ! getopts('f:m:i:L:dxA:F:I') ) {
usage();
exit;
}
($imapHost,$imapUser,$imapPwd) = split(/\//, $opt_i);
$mailfile = $opt_f;
$mbx = $opt_m;
$logfile = $opt_L;
$admin_user = $opt_A;
$msgs_per_folder = $opt_F;
$debug = 1 if $opt_d;
$showIMAP = 1;
if ( $logfile ) {
if ( ! open (LOG, ">> $logfile") ) {
print "Can't open logfile $logfile: $!\n";
$logfile = '';
}
}
Log("\nThis is mbxIMAPsync\n");
if ( !-e $mailfile ) {
Log("$mailfile does not exist");
exit;
}
# Determine whether we have SSL support via openSSL and IO::Socket::SSL
$ssl_installed = 1;
eval 'use IO::Socket::SSL';
if ( $@ ) {
$ssl_installed = 0;
}
}
sub usage {
print "Usage: mbxIMAPsync.pl\n";
print " -f <location of mailfiles>\n";
print " -i imapHost/imapUser/imapPassword\n";
print " -m <IMAP mailbox>\n";
print " [-L <logfile>]\n";
print " [-d debug]\n";
}
sub readMbox {
my $file = shift;
my @mail = ();
my $mail = [];
my $blank = 1;
local *FH;
local $_;
Log("Reading the mailfile") if $debug;
open(FH,"< $file") or die "Can't open $file";
while(<FH>) {
if($blank && /\AFrom .*\d{4}/) {
push(@mail, $mail) if scalar(@{$mail});
$mail = [ $_ ];
$blank = 0;
}
else {
$blank = m#\A\Z#o ? 1 : 0;
push(@{$mail}, $_);
}
}
push(@mail, $mail) if scalar(@{$mail});
close(FH);
return wantarray ? @mail : \@mail;
}
sub Log {
my $line = shift;
my $msg;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime (time);
$msg = sprintf ("%.2d-%.2d-%.4d.%.2d:%.2d:%.2d %s",
$mon + 1, $mday, $year + 1900, $hour, $min, $sec, $line);
if ( $logfile ) {
print LOG "$msg\n";
}
print STDERR "$line\n";
}
# Make a connection to a IMAP host
sub connectToHost {
my $host = shift;
my $conn = shift;
Log("Connecting to $host") if $debug;
($host,$port) = split(/:/, $host);
$port = 143 unless $port;
# We know whether to use SSL for ports 143 and 993. For any
# other ones we'll have to figure it out.
$mode = sslmode( $host, $port );
if ( $mode eq 'SSL' ) {
unless( $ssl_installed == 1 ) {
warn("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
Log("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
exit;
}
Log("Attempting an SSL connection") if $debug;
$$conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET,
);
unless ( $$conn ) {
$error = IO::Socket::SSL::errstr();
Log("Error connecting to $host: $error");
exit;
}
} else {
# Non-SSL connection
Log("Attempting a non-SSL connection") if $debug;
$$conn = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
);
unless ( $$conn ) {
Log("Error connecting to $host:$port: $@");
warn "Error connecting to $host:$port: $@";
exit;
}
}
# Log("Connected to $host on port $port");
}
sub sslmode {
my $host = shift;
my $port = shift;
my $mode;
# Determine whether to make an SSL connection
# to the host. Return 'SSL' if so.
if ( $port == 143 ) {
# Standard non-SSL port
return '';
} elsif ( $port == 993 ) {
# Standard SSL port
return 'SSL';
}
unless ( $ssl_installed ) {
# We don't have SSL installed on this machine
return '';
}
# For any other port we need to determine whether it supports SSL
my $conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
);
if ( $conn ) {
close( $conn );
$mode = 'SSL';
} else {
$mode = '';
}
return $mode;
}
#
# login in at the source host with the user's name and password
#
sub login {
my $user = shift;
my $pwd = shift;
my $conn = shift;
if ( $admin_user ) {
($admin_user,$admin_pwd) = split(/:/, $admin_user);
login_plain( $user, $admin_user, $admin_pwd, $conn ) or exit;
return 1;
}
if ( $pwd =~ /^oauth2:(.+)/i ) {
$token = $1;
Log("password is an OAUTH2 token");
login_xoauth2( $user, $token, $conn );
return 1;
}
Log("Logging in as $user") if $debug;
sendCommand ($conn, "1 LOGIN $user $pwd");
while (1) {
readResponse ( $conn );
if ($response =~ /^1 OK/i) {
last;
}
elsif ($response =~ /NO/) {
Log ("unexpected LOGIN response: $response");
return 0;
}
}
Log("Logged in as $user") if $debug;
return 1;
}
# login_plain
#
# login in at the source host with the user's name and password. If provided
# with administrator credential, use them as this eliminates the need for the
# user's password.
#
sub login_plain {
my $user = shift;
my $admin = shift;
my $pwd = shift;
my $conn = shift;
# Do an AUTHENTICATE = PLAIN. If an admin user has been provided then use it.
if ( !$admin ) {
# Log in as the user
$admin = $user
}
$login_str = sprintf("%s\x00%s\x00%s", $user,$admin,$pwd);
$login_str = encode_base64("$login_str", "");
$len = length( $login_str );
# sendCommand ($conn, "1 AUTHENTICATE \"PLAIN\" {$len}" );
sendCommand ($conn, "1 AUTHENTICATE PLAIN" );
my $loops;
while (1) {
readResponse ( $conn );
last if $response =~ /\+/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
sendCommand ($conn, "$login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /Microsoft Exchange/i and $conn eq $dst ) {
# The destination is an Exchange server
$exchange = 1;
Log("The destination is an Exchange server");
}
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
return 1;
}
# login_xoauth2
#
# login in at the source host with the user's name and an XOAUTH2 token.
#
sub login_xoauth2 {
my $user = shift;
my $token = shift;
my $conn = shift;
# Do an AUTHENTICATE = XOAUTH2 login
$login_str = encode_base64("user=". $user ."\x01auth=Bearer ". $token ."\x01\x01", '');
sendCommand ($conn, "1 AUTHENTICATE XOAUTH2 $login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /^\+ (.+)/ ) {
$error = decode_base64( $1 );
Log("XOAUTH authentication as $user failed: $error");
return 0;
}
last if $response =~ /^1 OK/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE|failed/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
$last if $loops++ > 5;
}
Log("login complete") if $debug;
return 1;
}
# logout
#
# log out from the host
#
sub logout {
my $conn = shift;
++$lsn;
undef @response;
sendCommand ($conn, "$lsn LOGOUT");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^$lsn OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected LOGOUT response: $response");
last;
}
}
close $conn;
return;
}
# readResponse
#
# This subroutine reads and formats an IMAP protocol response from an
# IMAP server on a specified connection.
#
sub readResponse
{
local($fd) = shift @_;
$response = <$fd>;
chop $response;
$response =~ s/\r//g;
push (@response,$response);
Log ("<< $response",2) if $showIMAP;
}
#
# sendCommand
#
# This subroutine formats and sends an IMAP protocol command to an
# IMAP server on a specified connection.
#
sub sendCommand
{
local($fd) = shift @_;
local($cmd) = shift @_;
print $fd "$cmd\r\n";
if ($showIMAP) { Log (">> $cmd",2); }
}
#
sub insertMsg {
my $mbx = shift;
my $message = shift;
my $flags = shift;
my $date = shift;
my $conn = shift;
my ($lsn,$lenx);
Log(" Inserting message into mailbox $mbx") if $debug;
$lenx = length($$message);
# Create the mailbox unless we have already done so
++$lsn;
if ($destMbxs{"$mbx"} eq '') {
Log("creating mailbox $mbx") if $debug;
sendCommand (IMAP, "$lsn CREATE \"$mbx\"");
while ( 1 ) {
readResponse (IMAP);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
if (!($response =~ /already exists|reserved mailbox name/i)) {
Log ("WARNING: $response");
}
last;
}
}
}
$destMbxs{"$mbx"} = '1';
++$lsn;
$flags =~ s/\\Recent//i;
# &sendCommand (IMAP, "$lsn APPEND \"$mbx\" ($flags) \"$date\" \{$lenx\}");
sendCommand (IMAP, "$lsn APPEND \"$mbx\" \{$lenx\}");
readResponse (IMAP);
if ( $response !~ /^\+/ ) {
Log ("unexpected APPEND response: $response");
# next;
push(@errors,"Error appending message to $mbx for $user");
return 0;
}
print IMAP "$$message\r\n";
undef @response;
while ( 1 ) {
readResponse (IMAP);
if ( $response =~ /^$lsn OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected APPEND response: $response");
# next;
return 0;
}
}
return 1;
}
# getMsgList
#
# Get a list of the user's messages in the indicated mailbox on
# the IMAP host
#
sub getMsgList {
my $mailbox = shift;
my $msgs = shift;
my $conn = shift;
my $seen;
my $empty;
my $msgnum;
Log("Getting list of msgs in $mailbox") if $debug;
trim( *mailbox );
sendCommand ($conn, "1 EXAMINE \"$mailbox\"");
undef @response;
$empty=0;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ / 0 EXISTS/i ) { $empty=1; }
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
# print STDERR "Error: $response\n";
return 0;
}
}
sendCommand ( $conn, "1 FETCH 1:* (uid flags internaldate body[header.fields (Message-Id)])");
undef @response;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
}
elsif ( $XDXDXD ) {
Log ("unexpected response: $response");
Log ("Unable to get list of messages in this mailbox");
push(@errors,"Error getting list of $user's msgs");
return 0;
}
}
# Get a list of the msgs in the mailbox
#
undef @msgs;
undef $flags;
for $i (0 .. $#response) {
$seen=0;
$_ = $response[$i];
last if /OK FETCH complete/;
if ( $response[$i] =~ /FETCH \(UID / ) {
$response[$i] =~ /\* ([^FETCH \(UID]*)/;
$msgnum = $1;
}
if ($response[$i] =~ /FLAGS/) {
# Get the list of flags
$response[$i] =~ /FLAGS \(([^\)]*)/;
$flags = $1;
$flags =~ s/\\Recent//i;
}
if ( $response[$i] =~ /INTERNALDATE ([^\)]*)/ ) {
### $response[$i] =~ /INTERNALDATE (.+) ([^BODY]*)/i;
$response[$i] =~ /INTERNALDATE (.+) BODY/i;
$date = $1;
$date =~ s/"//g;
}
if ( $response[$i] =~ /^Message-Id:/i ) {
($label,$msgid) = split(/: /, $response[$i]);
push (@$msgs,$msgid);
}
}
}
# trim
#
# remove leading and trailing spaces from a string
sub trim {
local (*string) = @_;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return;
}
sub findMsg {
my $msgid = shift;
my $mbx = shift;
my $conn = shift;
my $msgnum;
my $noSuchMbx;
Log("Searching for $msgid in $mbx") if $debug;
sendCommand ( $conn, "1 SELECT \"$mbx\"");
while (1) {
readResponse ($conn);
if ( $response =~ /^1 NO/ ) {
$noSuchMbx = 1;
last;
}
last if $response =~ /^1 OK/;
}
return '' if $noSuchMbx;
Log("Search for $msgid") if $debug;
sendCommand ( $conn, "1 SEARCH header Message-Id \"$msgid\"");
while (1) {
readResponse ($conn);
if ( $response =~ /\* SEARCH /i ) {
($dmy, $msgnum) = split(/\* SEARCH /i, $response);
($msgnum) = split(/ /, $msgnum);
}
last if $response =~ /^1 OK/;
last if $response =~ /complete/i;
}
if ( $msgnum ) {
Log("Message exists") if $debug;
} else {
Log("Message does not exist") if $debug;
}
return $msgnum;
}
sub deleteMsg {
my $msgid = shift;
my $mbx = shift;
my $conn = shift;
my $rc;
Log("Deleting message $msgid") if $debug;
$msgnum = findMsg( $msgid, $mbx, $conn );
sendCommand ( $conn, "1 STORE $msgnum +FLAGS (\\Deleted)");
while (1) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
$rc = 1;
Log(" Marked $msgid for delete");
last;
}
if ( $response =~ /^1 BAD|^1 NO/i ) {
Log("Error setting \Deleted flag for msg $msgnum: $response");
$rc = 0;
last;
}
}
return $rc;
}
sub expungeMbx {
my $mbx = shift;
my $conn = shift;
my $purged=0;
Log("Purging $mbx") if $debug;
sendCommand ( $conn, "1 SELECT \"$mbx\"");
while (1) {
readResponse ($conn);
last if $response =~ /^1 OK/;
if ( $response =~ /^1 NO|^1 BAD/i ) {
Log("Error selecting mailbox $mbx: $response");
last;
}
}
sendCommand ( $conn, "1 EXPUNGE");
while (1) {
readResponse ($conn);
last if $response =~ /^1 OK/;
$purged++ if $response =~ /EXPUNGE/i;
if ( $response =~ /^1 BAD|^1 NO/i ) {
print STDOUT "Error expunging messages: $response\n";
last;
}
}
return $purged;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,797 +0,0 @@
#!/usr/bin/perl
# $Header: /mhub4/sources/imap-tools/purgeMbx.pl,v 1.7 2015/06/05 11:32:25 rick Exp $
############################################################################
# Program name purgeMbx.pl #
# Written by Rick Sanders #
# Date 5/24/2008 #
# #
# Description #
# #
# This script deletes all of the messages in a user's IMAP #
# mailbox. #
# #
# purgeMbx.pl is called like this: #
# ./purgeMbx.pl -s host/user/password -m <mailbox> #
# #
# Note that the mailbox name is case-sensitive. #
# #
# Optional arguments: #
# -d debug #
# -L <logfile> #
############################################################################
############################################################################
# Copyright (c) 2008 Rick Sanders <rfs9999@earthlink.net> #
# #
# Permission to use, copy, modify, and distribute this software for any #
# purpose with or without fee is hereby granted, provided that the above #
# copyright notice and this permission notice appear in all copies. #
# #
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES #
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR #
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES #
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN #
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF #
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #
############################################################################
use Socket;
use FileHandle;
use Fcntl;
use Getopt::Std;
use IO::Socket;
use MIME::Base64 qw(encode_base64 decode_base64 );
#################################################################
# Main program. #
#################################################################
init();
sigprc();
# Get list of all messages on the source host by Message-Id
#
connectToHost($host, \$conn);
login($user,$pwd, $conn) or exit;
if ( $mbx eq '*' ) {
@mailboxes = listMailboxes( '*', $conn);
} else {
push( @mailboxes, $mbx );
}
foreach $mbx ( @mailboxes ) {
Log("Purging the \"$mbx\" mailbox");
@sourceMsgs = ();
getMsgList( $mbx, \@msgs, $conn );
Log("$mbx mailbox is empty") unless @msgs;
foreach $msgnum ( @msgs ) {
$total++;
deleteMsg( $msgnum, $conn );
}
expungeMbx( $mbx, $conn ) if @msgs;
Log("$total messages were deleted from \"$mbx\" mailbox");
}
logout( $conn );
exit;
sub init {
$version = 'V1.0.1';
$os = $ENV{'OS'};
processArgs();
# Determine whether we have SSL support via openSSL and IO::Socket::SSL
$ssl_installed = 1;
eval 'use IO::Socket::SSL';
if ( $@ ) {
$ssl_installed = 0;
}
$timeout = 60 unless $timeout;
# Open the logFile
#
if ( $logfile ) {
if ( !open(LOG, ">> $logfile")) {
print STDOUT "Can't open $logfile: $!\n";
}
select(LOG); $| = 1;
}
Log("\n$0 starting");
$total=0;
}
#
# sendCommand
#
# This subroutine formats and sends an IMAP protocol command to an
# IMAP server on a specified connection.
#
sub sendCommand
{
local($fd) = shift @_;
local($cmd) = shift @_;
print $fd "$cmd\r\n";
if ($showIMAP) { Log (">> $cmd",2); }
}
#
# readResponse
#
# This subroutine reads and formats an IMAP protocol response from an
# IMAP server on a specified connection.
#
sub readResponse
{
local($fd) = shift @_;
$response = <$fd>;
chop $response;
$response =~ s/\r//g;
push (@response,$response);
if ($showIMAP) { Log ("<< $response",2); }
}
#
# Log
#
# This subroutine formats and writes a log message to STDERR.
#
sub Log {
my $str = shift;
# If a logile has been specified then write the output to it
# Otherwise write it to STDOUT
if ( $logfile ) {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
if ($year < 99) { $yr = 2000; }
else { $yr = 1900; }
$line = sprintf ("%.2d-%.2d-%d.%.2d:%.2d:%.2d %s %s\n",
$mon + 1, $mday, $year + $yr, $hour, $min, $sec,$$,$str);
print LOG "$line";
}
print STDOUT "$str\n";
}
# Make a connection to an IMAP host
sub connectToHost {
my $host = shift;
my $conn = shift;
Log("Connecting to $host") if $debug;
($host,$port) = split(/:/, $host);
$port = 143 unless $port;
# We know whether to use SSL for ports 143 and 993. For any
# other ones we'll have to figure it out.
$mode = sslmode( $host, $port );
if ( $mode eq 'SSL' ) {
unless( $ssl_installed == 1 ) {
warn("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
Log("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
exit;
}
Log("Attempting an SSL connection") if $debug;
$$conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET,
);
unless ( $$conn ) {
$error = IO::Socket::SSL::errstr();
Log("Error connecting to $host: $error");
warn("Error connecting to $host: $error");
exit;
}
} else {
# Non-SSL connection
Log("Attempting a non-SSL connection") if $debug;
$$conn = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
);
unless ( $$conn ) {
Log("Error connecting to $host:$port: $@");
warn "Error connecting to $host:$port: $@";
exit;
}
}
Log("Connected to $host on port $port");
}
sub sslmode {
my $host = shift;
my $port = shift;
my $mode;
# Determine whether to make an SSL connection
# to the host. Return 'SSL' if so.
if ( $port == 143 ) {
# Standard non-SSL port
return '';
} elsif ( $port == 993 ) {
# Standard SSL port
return 'SSL';
}
unless ( $ssl_installed ) {
# We don't have SSL installed on this machine
return '';
}
# For any other port we need to determine whether it supports SSL
my $conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
);
if ( $conn ) {
close( $conn );
$mode = 'SSL';
} else {
$mode = '';
}
return $mode;
}
# trim
#
# remove leading and trailing spaces from a string
sub trim {
local (*string) = @_;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return;
}
# login
#
# login in at the source host with the user's name and password
#
sub login {
my $user = shift;
my $pwd = shift;
my $conn = shift;
if ( $admin_user ) {
($admin_user,$admin_pwd) = split(/:/, $admin_user);
login_plain( $user, $admin_user, $admin_pwd, $conn ) or exit;
return 1;
}
if ( $pwd =~ /^oauth2:(.+)/i ) {
$token = $1;
Log("password is an OAUTH2 token");
login_xoauth2( $user, $token, $conn );
return 1;
}
sendCommand ($conn, "1 LOGIN $user $pwd");
while (1) {
readResponse ( $conn );
if ($response =~ /1 OK/i) {
last;
}
if ($response =~ /^(.+) NO|^(.+) BAD/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
}
Log("Logged in as $user") if $debug;
return 1;
}
# login_plain
#
# login in at the source host with the user's name and password. If provided
# with administrator credential, use them as this eliminates the need for the
# user's password.
#
sub login_plain {
my $user = shift;
my $admin = shift;
my $pwd = shift;
my $conn = shift;
# Do an AUTHENTICATE = PLAIN. If an admin user has been provided then use it.
if ( !$admin ) {
# Log in as the user
$admin = $user
}
$login_str = sprintf("%s\x00%s\x00%s", $user,$admin,$pwd);
$login_str = encode_base64("$login_str", "");
$len = length( $login_str );
# sendCommand ($conn, "1 AUTHENTICATE \"PLAIN\" {$len}" );
sendCommand ($conn, "1 AUTHENTICATE PLAIN" );
my $loops;
while (1) {
readResponse ( $conn );
last if $response =~ /\+/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
sendCommand ($conn, "$login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /Microsoft Exchange/i and $conn eq $dst ) {
# The destination is an Exchange server
$exchange = 1;
Log("The destination is an Exchange server");
}
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
exit;
}
$last if $loops++ > 5;
}
return 1;
}
# login_xoauth2
#
# login in at the source host with the user's name and an XOAUTH2 token.
#
sub login_xoauth2 {
my $user = shift;
my $token = shift;
my $conn = shift;
# Do an AUTHENTICATE = XOAUTH2 login
$login_str = encode_base64("user=". $user ."\x01auth=Bearer ". $token ."\x01\x01", '');
sendCommand ($conn, "1 AUTHENTICATE XOAUTH2 $login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /^\+ (.+)/ ) {
$error = decode_base64( $1 );
Log("XOAUTH authentication as $user failed: $error");
return 0;
}
last if $response =~ /^1 OK/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE|failed/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
$last if $loops++ > 5;
}
Log("login complete") if $debug;
return 1;
}
# logout
#
# log out from the host
#
sub logout {
my $conn = shift;
++$lsn;
undef @response;
sendCommand ($conn, "$lsn LOGOUT");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^$lsn OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected LOGOUT response: $response");
last;
}
}
close $conn;
return;
}
# getMsgList
#
# Get a list of messages in a mailbox
#
sub getMsgList {
my $mailbox = shift;
my $msgs = shift;
my $conn = shift;
my $seen;
my $empty;
my $msgnum;
my $from;
my $flags;
trim( *mailbox );
sendCommand ($conn, "1 SELECT \"$mailbox\"");
undef @response;
$empty=0;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ / 0 EXISTS/i ) { $empty=1; }
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
# print STDERR "Error: $response\n";
return 0;
}
}
sendCommand ( $conn, "1 FETCH 1:* (uid flags internaldate body[header.fields (From Date)])");
undef @response;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
}
last if $response =~ /^1 NO|^1 BAD/;
}
@msgs = ();
$flags = '';
for $i (0 .. $#response) {
last if $response[$i] =~ /^1 OK FETCH complete/i;
if ($response[$i] =~ /FLAGS/) {
# Get the list of flags
$response[$i] =~ /FLAGS \(([^\)]*)/;
$flags = $1;
$flags =~ s/\\Recent//;
}
if ( $response[$i] =~ /INTERNALDATE/) {
$response[$i] =~ /INTERNALDATE (.+) BODY/;
# $response[$i] =~ /INTERNALDATE "(.+)" BODY/;
$date = $1;
$date =~ /"(.+)"/;
$date = $1;
$date =~ s/"//g;
}
# if ( $response[$i] =~ /\* (.+) [^FETCH]/ ) {
if ( $response[$i] =~ /\* (.+) FETCH/ ) {
($msgnum) = split(/\s+/, $1);
}
if ( $msgnum && $date ) {
push (@$msgs, $msgnum);
$msgnum = $date = '';
}
}
}
sub fetchMsg {
my $msgnum = shift;
my $mbx = shift;
my $conn = shift;
my $message;
Log(" Fetching msg $msgnum...") if $debug;
sendCommand ($conn, "1 SELECT \"$mbx\"");
while (1) {
readResponse ($conn);
last if ( $response =~ /1 OK/i );
}
sendCommand( $conn, "1 FETCH $msgnum (rfc822)");
while (1) {
readResponse ($conn);
if ( $response =~ /1 OK/i ) {
$size = length($message);
last;
}
elsif ($response =~ /message number out of range/i) {
Log ("Error fetching uid $uid: out of range",2);
$stat=0;
last;
}
elsif ($response =~ /Bogus sequence in FETCH/i) {
Log ("Error fetching uid $uid: Bogus sequence in FETCH",2);
$stat=0;
last;
}
elsif ( $response =~ /message could not be processed/i ) {
Log("Message could not be processed, skipping it ($user,msgnum $msgnum,$destMbx)");
push(@errors,"Message could not be processed, skipping it ($user,msgnum $msgnum,$destMbx)");
$stat=0;
last;
}
elsif
($response =~ /^\*\s+$msgnum\s+FETCH\s+\(.*RFC822\s+\{[0-9]+\}/i) {
($len) = ($response =~ /^\*\s+$msgnum\s+FETCH\s+\(.*RFC822\s+\{([0-9]+)\}/i);
$cc = 0;
$message = "";
while ( $cc < $len ) {
$n = 0;
$n = read ($conn, $segment, $len - $cc);
if ( $n == 0 ) {
Log ("unable to read $len bytes");
return 0;
}
$message .= $segment;
$cc += $n;
}
}
}
return $message;
}
sub usage {
print STDOUT "usage:\n";
print STDOUT " purgeMbx.pl -S host/user/pwd -m <mbx>\n";
print STDOUT " Optional arguments:\n";
print STDOUT " -d debug\n";
print STDOUT " -L <logfile>\n";
print STDOUT " -A <admin_user:admin_password>\n";
exit;
}
sub processArgs {
if ( !getopts( "dIs:L:m:hA:" ) ) {
usage();
}
($host,$user,$pwd) = split(/\//, $opt_s);
$mbx = $opt_m;
$admin_user = $opt_A;
$logfile = $opt_L;
$debug = $showIMAP = 1 if $opt_d;
$showIMAP = 1 if $opt_I;
usage() if $opt_h;
}
sub deleteMsg {
my $msgnum = shift;
my $conn = shift;
my $rc;
sendCommand ( $conn, "1 STORE $msgnum +FLAGS (\\Deleted)");
while (1) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
$rc = 1;
Log(" Marked msg number $msgnum for delete") if $debug;
last;
}
if ( $response =~ /^1 BAD|^1 NO/i ) {
Log("Error setting \Deleted flag for msg $msgnum: $response");
$rc = 0;
last;
}
}
return $rc;
}
sub expungeMbx {
my $mbx = shift;
my $conn = shift;
print STDOUT "Purging mailbox $mbx..." if $debug;
sendCommand ($conn, "1 SELECT \"$mbx\"");
while (1) {
readResponse ($conn);
last if ( $response =~ /1 OK/i );
}
sendCommand ( $conn, "1 EXPUNGE");
$expunged=0;
while (1) {
readResponse ($conn);
$expunged++ if $response =~ /\* (.+) Expunge/i;
last if $response =~ /^1 OK/;
if ( $response =~ /^1 BAD|^1 NO/i ) {
print STDOUT "Error purging messages: $response\n";
last;
}
}
$totalExpunged += $expunged;
# print STDOUT "$expunged messages purged\n" if $debug;
}
sub dieright {
local($sig) = @_;
print STDOUT "caught signal $sig\n";
logout( $conn );
exit(-1);
}
sub sigprc {
$SIG{'HUP'} = 'dieright';
$SIG{'INT'} = 'dieright';
$SIG{'QUIT'} = 'dieright';
$SIG{'ILL'} = 'dieright';
$SIG{'TRAP'} = 'dieright';
$SIG{'IOT'} = 'dieright';
$SIG{'EMT'} = 'dieright';
$SIG{'FPE'} = 'dieright';
$SIG{'BUS'} = 'dieright';
$SIG{'SEGV'} = 'dieright';
$SIG{'SYS'} = 'dieright';
$SIG{'PIPE'} = 'dieright';
$SIG{'ALRM'} = 'dieright';
$SIG{'TERM'} = 'dieright';
$SIG{'URG'} = 'dieright';
}
# getMailboxList
#
# get a list of the user's mailboxes
#
sub getMailboxList {
my $conn = shift;
my @mbxs;
my $mbx;
# Get a list of the user's mailboxes
#
Log("Get list of user's mailboxes") if $debug;
sendCommand ($conn, "1 LIST \"\" *");
undef @response;
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
return 0;
}
}
undef @mbxs;
for $i (0 .. $#response) {
$response[$i] =~ s/\s+/ /;
($dmy,$mbx) = split(/"\/"/,$response[$i]);
$mbx =~ s/^\s+//; $mbx =~ s/\s+$//;
$mbx =~ s/"//g;
if ($response[$i] =~ /NOSELECT/i) {
if ($debugMode) { Log("$mbx is set NOSELECT,skip it",2); }
next;
}
if ($mbx =~ /^\./) {
# Skip mailboxes starting with a dot
next;
}
push ( @mbxs, $mbx ) if $mbx ne '';
}
return @mbxs;
}
# listMailboxes
#
# Get a list of the user's mailboxes
#
sub listMailboxes {
my $mbx = shift;
my $conn = shift;
my @mbxs;
sendCommand ($conn, "1 LIST \"\" \"$mbx\"");
undef @response;
while ( 1 ) {
&readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
&Log ("unexpected response: $response");
return 0;
}
}
@mbxs = ();
for $i (0 .. $#response) {
$response[$i] =~ s/\s+/ /;
if ( $response[$i] =~ /"$/ ) {
$response[$i] =~ /\* LIST \((.*)\) "(.+)" "(.+)"/i;
$mbx = $3;
} elsif ( $response[$i] =~ /\* LIST \((.*)\) NIL (.+)/i ) {
$mbx = $2;
} else {
$response[$i] =~ /\* LIST \((.*)\) "(.+)" (.+)/i;
$mbx = $3;
}
$mbx =~ s/^\s+//; $mbx =~ s/\s+$//;
if ($response[$i] =~ /NOSELECT/i) {
$nosel_mbxs{"$mbx"} = 1;
}
push ( @mbxs, $mbx ) if $mbx ne '';
}
return @mbxs;
}

View File

@ -1,76 +0,0 @@
Release notes for IMAP-Tools version 1.291.
Changes since 2014/06/12:
dumptoIMAP.pl 1.12 2014/06/21
Fix handling of delimter and prefix when server does not supply NAMESPACE via -y argument.
dumptoIMAP.pl 1.11 2014/06/20
Fix problem in get_mbx_list caused by the path not being as expected and causing the filespec to not have a leading '/'
imap_audit.pl 1.6 2014/07/24
Added support for "before date" and "after date" audits. Also added building of "dummy" msgids for messages lacking them.
imapcopy.pl 1.138 2014/07/21
Added -O argument to tell imapcopy that both servers are Dovecot using the brain-dead mbox format where mailboxes can have messages or submailboxes but not both.
imapcopy.pl 1.136 2014/07/21
Added -o <destination mailbox> to permit all messages to be copied to a single "archive" mailbox on the destination (and not to the regular mailboxes.)
Prompt the user for source/dest user password if the password = PROMPT
imapcopy.pl 1.129 2014/07/02
When building dummy msgids use the Date in the header rather than the INTERNALDATE. It seems that a server may adjust the internaldate according to its timezone.
imapcopy.pl 1.128 2014/07/02
Tweak detection of message size because gmail doesn't send it the way most servers do.
imapcopy.pl 1.127 2014/06/27
Two changes: If a message does not have a Message-ID then build one for it from the Sender, Subject, and INTERNALDATE fields. So the same for the source and destination servers. If -l is set (dont_copy_source_dups) then duplicates on the source will not be copied.
imapcopy.pl 1.126 2014/06/16
Add a 'special date' search function for a customer whose SEARCH command seems to be unreliable. This routine manually compares the INTERNALDATES with the value of -J 'SINCE|BEFORE <date>' argument.
imapcopy.pl 1.125 2014/06/13
Notify msg to dest user with Subject of messages excluded because they exceed the maximum size argument
imapcopy.pl 1.123 2014/06/13
Removed 'from the dest' from sub expunge() since the -r option can be used to purge messages on the source that have been copied.
imapsync.pl 1.62 2014/07/19
Add support for backslash as delimiter for -S and -D host/user/pwd
imapsync.pl 1.60 2014/07/05
Fix the getDatedMsg subroutine for built msgids.
imapsync.pl 1.58 2014/07/05
Include the subject in the constructed msgid.
imapsync.pl 1.56 2014/07/05
Build msgid from date,subject,sender if msgid is missing.
migrateIMAP.pl 1.54 2014/07/11
Use from+header_date+subject for msgid if message lacks one.
pop3toimap.pl 1.8 2014/07/06
Fix problem reading users file on Windows (last character was chopped off).
thunderbird_to_imap.pl 1.12 2014/07/09
Added a range selector to deal with out-of-memory errors
thunderbird_to_imap.pl 1.11 2014/07/09
Fix the way Tbird status codes are interpreted
thunderbird_to_imap.pl 1.10 2014/07/07
Fixed problem with CRLF on some Windows boxes, added complete set of Thunderbird Mozilla status flags.
thunderbird_to_imap.pl 1.9 2014/07/01
Don't print 'running in update mode' unless -U is set.
thunderbird_to_imap.pl 1.8 2014/07/01
Tweak the end-of-message check because some Thunderbird folders have just "From " instead of "From xxxxxxxx"
thunderbird_to_imap.pl 1.6 2014/06/29
Enhance the date-formatting code.
thunderbird_to_imap.pl 1.5 2014/06/28
Fix opt_x which was used for two purposes; add opt_X (CRLF control) in its place.

View File

@ -1,30 +0,0 @@
Release notes for IMAP-Tools version 1.298.
Changes since 2014/07/25:
The release notes for earlier versions can be found at http://www.athensfbc.com/release_notes
imap_audit.pl 1.15 2014/08/25
Added -n argument to compare only the message counts on src and dest.
Add more loop detection code
Open mbxs in RO mode
imap_audit.pl 1.12 2014/07/27
Strip off timezone offset when building dummy msgid
imap_audit.pl 1.11 2014/07/26
Added -g argument to force use of dummy msgids for all messages
imap_audit.pl 1.10 2014/07/26
If Message-ID line is wrapped get it from following line
imapcopy.cgi 1.9 2014/08/18
Make the 'Cannot redirect to STDERR' error message more informative.
imapfilter.pl 1.46 2014/09/01
Fixed 'test' mode counters.
Add support for numeric date offsets instead of fixed dates in ISEARCH rules
Fix issue with chunking of messages. Add -X <Trash> argument for emptying the Trash folder at the end of the run.
imapsync.pl 1.63 2014/08/26
Added -t (dry run) feature.

View File

@ -1,95 +0,0 @@
Release notes for IMAP-Tools version 1.300.
Changes since 2014/09/03:
The release notes for earlier versions can be found at http://www.athensfbc.com/release_notes
IMAPtoMbox.pl 1.11 2014/10/15
Added support for oauth2 logins
MboxtoIMAP.pl 1.21 2014/10/15
Add 'use decode_base64' for OAUTH2 login error message
MboxtoIMAP.pl 1.20 2014/10/15
Added support for OAUTH2 logins
delIMAPdups.pl 1.26 2014/10/15
Added support for oauth2 logins
delete_imap_mailboxes.pl 1.7 2014/10/17
Mark INBOX messages for delete with single 1:* command instead of individually
delete_imap_mailboxes.pl 1.6 2014/10/15
Added support for oauth2 logins
delete_imap_mailboxes.pl 1.5 2014/10/15
Drop -i argument for purging the INBOX and make it automatic.
delete_imap_mailboxes.pl 1.4 2014/10/14
Added -i argument to purge the inbox.
dumptoIMAP.pl 1.13 2014/10/15
Added support for oauth2 logins
imapCapability.pl 1.9 2014/10/15
Added support for oauth2 logins
imap_audit.pl 1.16 2014/10/15
Added support for oauth2 logins
imap_search.pl 1.3 2014/10/17
Added support for oauth2 logins
imap_to_maildir.pl 1.5 2014/10/15
Added support for oauth2 logins
imapcopy.pl 1.141 2014/10/14
Added support for Gmail oauth2 tokens.
imapcopy.pl 1.140 2014/10/09
Openwave the source mailbox in EXAMINE mode since a few servers otherwise mark the messages as SEEN.
imapdump.pl 1.29 2014/10/15
Added support for oauth2 logins
imapdump.pl 1.28 2014/09/06
Improve logging in debug mode
imapfilter.pl 1.47 2014/10/14
Added support for oauth2 tokens
imapsync.pl 1.65 2014/10/15
Added support for OAUTH2 logins
imapsync.pl 1.64 2014/09/05
Added source_archive feature that moves messages from a source mailbox in an archive mailbox, also on the source.
list_account_sizes.pl 1.9 2014/10/15
Added support for oauth2 logins
list_imap_folders.pl 1.15 2014/10/15
Added support for oauth2 logins
maildir_to_imap.pl 1.7 2014/10/15
Added support for oauth2 logins
mbxIMAPsync.pl 1.1 2014/10/16
Added support for oauth2 logins
mbxIMAPsync.pl 1.2 2014/10/16
Added support for oauth2 logins
migrateIMAP.pl 1.55 2014/10/16
Added support for oauth2 logins
pop3toimap.pl 1.10 2014/10/16
Added support for oauth2 logins
purgeMbx.pl 1.5 2014/10/16
Added support for oauth2 logins
thunderbird_to_imap.pl 1.13 2014/10/16
Added support for oauth2 logins
trash.pl 1.5 2014/10/16
Added support for oauth2 logins

View File

@ -1,30 +0,0 @@
Release notes for IMAP-Tools version 1.303.
Changes since 20141017:
The release notes for earlier versions can be found at http://www.athensfbc.com/release_notes
dumptoIMAP.pl 1.14 2014/11/10
Correct -S host/user/pwd to -i host/user/pwd in the notes at the top of the script.
imapcopy.pl 1.143 2014/11/18
Added -V argument to handle the response from Zimbra 6.0.16 which is not sending a closing ')' line in its response to the FETCH header items. Instead of ')' imapcopy considers ' FLAGS xxxxx' as the end of the FETCHED data.
imapcopy.pl 1.142 2014/11/06
Removed 'server unvailable' error trap so that if that phrase appears in the text of a message it won't trigger a reconnect() action.
list_imap_folders.pl 1.18 2014/11/18
Added ability to process list of users, added message subject to large message report.
list_imap_folders.pl 1.17 2014/11/18
Added 'subject' field to large message report and fixed the -U argument.
list_imap_folders.pl 1.16 2014/11/15
Add support for UWash-imap style mailboxes (MH)
maildir_to_imap.pl 1.9 2014/10/31
Added -M <maildir_folder:imap_mbx> argument so the user can change the name of the IMAP mailbox to be different than the maildir folder name.
maildir_to_imap.pl 1.8 2014/10/30
Require call to ctime() which is not needed.

View File

@ -1,47 +0,0 @@
Release notes for IMAP-Tools version 1.313.
Changes since 2014/12/09:
The release notes for earlier versions can be found at http://www.athensfbc.com/release_notes
IMAPtoMbox.pl 1.12 2015/02/02
Fixed IMAP FETCH parsing
delIMAPdups.pl 1.28 2015/01/29
Added -r <range> argument for message range to check, eg -r 1:1000
delIMAPdups.pl.files 1.2 2015/01/30
-p argument was not being honored.
imap_audit.pl 1.18 2015/02/02
Fixed problem with IMAP FETCH parsing
imap_audit.pl 1.17 2015/01/31
Increase max loop counter
imap_search.pl 1.4 2015/02/02
Fixed IMAP FETCH parsing
imapcopy.pl 1.146 2015/02/01
Fixed FETCH parsing bug exposed by new Zimbra version.
imapcopy.pl 1.145 2015/01/22
Add a "skip message-id" option using imapcopy.skip to hold msgs to be skipped
imapdump.pl 1.34 2015/02/02
Fixed IMAP FETCH parsing
imapfilter.pl 1.48 2015/01/23
Added -T <mailbox> feature which processes a mailbox and its subfolders only.
imapsync.pl 1.66 2015/02/02
Fetch problem with IMAP FETCH parsing
migrateIMAP.pl 1.58 2015/02/01
Fixed FETCH parser bug
migrateIMAP.pl 1.57 2015/01/27
Skip the [Gmail]/All Mail folder
migrateIMAP.pl 1.56 2015/01/21
Detect a * BYE response from the server when fetching messages headers and exit.

View File

@ -1,116 +0,0 @@
Release notes for IMAP-Tools version 1.326.
Changes since 2015/02/03:
The release notes for earlier versions can be found at http://www.athensfbc.com/release_notes
IMAPtoMbox.pl 1.13 2015/04/30
The From address was missing from the first line in the message in the mbox file.
delIMAPdups.pl 1.30 2015/03/07
sub getDelimiter was missing
delIMAPdups.pl 1.29 2015/03/07
Fixed truncated line in code.
delIMAPdups.pl.files 1.3 2015/02/04
Added -g (global) option
email_archive.pl 1.6 2015/02/21
Clean up code for production release
email_attachment_cleaner.pl 1.6 2015/03/04
Add option to save attachments but not strip them. Add option to specify list of attachments types.
email_attachment_cleaner.pl 1.5 2015/03/03
Fix counter bug
email_attachment_cleaner.pl 1.4 2015/03/03
Call validate_date() after get_date()
email_attachment_cleaner.pl 1.3 2015/03/03
Fixes for test mode
email_attachment_cleaner.pl 1.2 2015/03/02
Added some error checking
email_restore.cgi 1.1 2015/03/01
Initial version =============================================================================
email_restore.cgi 1.4 2015/02/21
Clean up code for production release
imap_audit.pl 1.20 2015/04/03
Fix for multi-line Message-ID in message header
imap_audit.pl 1.19 2015/02/06
Fixed a bug in the auth plain login routine
imap_cleaner.pl 1.5 2015/02/27
Add -O <dir> option to save attachments in the specified directory
imap_cleaner.pl 1.4 2015/02/27
Added -u and -p arguments for username and password. Removed list option.
imap_cleaner.pl 1.3 2015/02/27
Added -U <user:password> argument
imap_cleaner.pl 1.2 2015/02/25
Comment out date fixup code (not needed). Added test option
imapcopy.pl 1.157 2015/05/22
Enhance reconnect() mode.
imapcopy.pl 1.156 2015/05/19
Workaround to rename mailboxes with INBOX. prefix that shouldn't be there on the destination.
imapcopy.pl 1.155 2015/04/26
Set the $exchange flag in AUTH PLAIN login mode if the destination is an Exchange server
imapcopy.pl 1.154 2015/04/24
Tweak the mailbox mapping rules for the case where the source delimiter is an '_' character.
imapcopy.pl 1.153 2015/04/22
Nested folders on destination not created correctly when source delimiter is a backslash character
imapcopy.pl 1.152 2015/04/18
Added some additional error handling for Exchange-related errors
imapcopy.pl 1.151 2015/04/11
Don't skip mailboxes starting with a dot.
imapcopy.pl 1.150 2015/04/03
Added fix for multi-line Message-IDs to dated message search routine.
imapcopy.pl 1.149 2015/04/03
Fix for multi-line Message-ID line in the header in update mode.
imapcopy.pl 1.148 2015/04/01
Don't let a child process try to launch another child process in Parallel mode.
imapcopy.pl 1.147 2015/03/21
Make -R argument apply to exclude-mailboxes as well as include-mailboxes
imapdump.pl 1.36 2015/03/05
Added option to include all flags (not just S = seen) in the dumped filename. Also option to include custom flags, not just standard IMAP flags. And option to update the flags when they change on the server.
imapdump.pl 1.35 2015/03/04
Build dummy msgid if the message lacks one.
imapsync.pl 1.67 2015/04/03
Fix for multi-line msgids in message header
list_imap_folders.pl 1.25 2015/02/16
Put a space between "fields" and "(Subject)" in body.peek command. The Rocklife MailSite IMAP server wants it that way.
migrateIMAP.pl 1.60 2015/05/20
Handle the way that Domino responds to LIST command for nested mailboxes
migrateIMAP.pl 1.59 2015/04/05
Fix for multi-line message-id
reload_archived_msgs.pl 1.1 2015/02/21
Initial release =============================================================================
thunderbird_to_imap.pl 1.14 2015/03/15
Use eval to protect against substr errors

View File

@ -1,14 +0,0 @@
Release notes for IMAP-Tools version V1.309.
Changes since 2014/11/19:
The release notes for earlier versions can be found at http://www.athensfbc.com/release_notes
delIMAPdups.pl 1.27 2014/11/22
Accept either a space or colon as separator in users file.
imapdump.pl 1.31 2014/12/07
Added parallel mode, multi-user mode, and extract-attachments-as-separate files option.
list_imap_folders.pl 1.24 2014/11/22
When writing large message report don't call UTF-7 mailboxname conversion if the server doesn't have Perl support for it.

File diff suppressed because it is too large Load Diff

View File

@ -1,993 +0,0 @@
#!/usr/bin/perl
# $Header: /mhub4/sources/imap-tools/trash.pl,v 1.5 2014/10/16 01:18:31 rick Exp $
#######################################################################
# Description #
# #
# This script checks a user's IMAP mailboxes for deleted messages #
# which it moves to the trash mailbox. Optionally the trash #
# mailbox is emptied. #
# #
# trash.pl is called like this: #
# ./trash.pl -S host/user/password #
# #
# Optional arguments: #
# -i <user file> format: user password, omit pwd if -a #
# -d debug #
# -t <trash mailbox name> (defaults to 'Trash') #
# -e empty the trash mailbox (default is not to empty it) #
# -a <admin user:admin password> #
# -L <logfile> #
# -m mailbox list (check just certain mailboxes,see usage notes)#
#######################################################################
use Socket;
use FileHandle;
use Fcntl;
use Getopt::Std;
use MIME::Base64 qw(encode_base64 decode_base64);
use IO::Socket::INET;
use IO::Socket::SSL;
#################################################################
# Main program. #
#################################################################
init();
sigprc();
$n = scalar @users;
Log("There are $n users");
foreach $_ ( @users ) {
s/^\s+|\s$//g;
($sourceUser,$sourcePwd) = split(/\s+/, $_);
Log("$sourceUser");
# Get list of all messages on the source host by Message-Id
#
next unless connectToHost($sourceHost, \$src );
if ( $admin_user ) {
# Do an admin login using AUTHENTICATION = PLAIN
Log( "Login admin:" .$sourceUser."---". $admin_user ."---". $admin_pwd ) if $verbose;
login_plain( $sourceUser, $admin_user, $admin_pwd, $src );
} else {
Log("Normal:".$sourceUser ."---".$sourcePwd) if $verbose;
next unless login($sourceUser,$sourcePwd, $src);
}
createMbx( $trash, $src ) unless mbxExists( $trash, $src);
@mbxs = getMailboxList($sourceUser, $src);
Log("Checking mailboxes for deleted messages") if $debug;
$total=0;
foreach $mbx ( @mbxs ) {
next if $mbx eq $trash;
next if $nosel_mbxs{"$mbx"};
Log(" Checking mailbox $mbx") if $verbose;
%msgList = ();
@sourceMsgs = ();
find_deleted_msgs( $mbx, \$msglist, $src );
moveToTrash( $mbx, $trash, \$msglist, $src );
expungeMbx( $mbx, $src );
}
Log("$total messages were moved to $trash");
if ( $emptyTrash and ($total > 0) ) {
expungeMbx( $trash, $src );
Log("The $trash mailbox has been emptied");
}
logout( $src );
$total_users++;
$total_moved += $total;
}
Log("Done.");
Log("Summary:");
Log(" Users processed $total_users");
Log(" Messages moved $total_moved");
exit;
sub init {
$version = 'V1.0';
$os = $ENV{'OS'};
&processArgs;
if ($timeout eq '') { $timeout = 60; }
# Open the logFile
#
if ( $logfile ) {
if ( !open(LOG, ">> $logfile")) {
print STDOUT "Can't open $logfile: $!\n";
}
select(LOG); $| = 1;
}
Log("\n$0 starting");
$total=0;
# Determine whether we have SSL support via openSSL and IO::Socket::SSL
$ssl_installed = 1;
eval 'use IO::Socket::SSL';
if ( $@ ) {
$ssl_installed = 0;
}
}
#
# sendCommand
#
# This subroutine formats and sends an IMAP protocol command to an
# IMAP server on a specified connection.
#
sub sendCommand
{
local($fd) = shift @_;
local($cmd) = shift @_;
print $fd "$cmd\r\n";
if ($showIMAP) { Log (">> $cmd",2); }
}
#
# readResponse
#
# This subroutine reads and formats an IMAP protocol response from an
# IMAP server on a specified connection.
#
sub readResponse
{
local($fd) = shift @_;
$response = <$fd>;
chop $response;
$response =~ s/\r//g;
push (@response,$response);
if ($showIMAP) { Log ("<< $response",2); }
}
#
# Log
#
# This subroutine formats and writes a log message to STDERR.
#
sub Log {
my $str = shift;
# If a logile has been specified then write the output to it
# Otherwise write it to STDOUT
if ( $logfile ) {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
if ($year < 99) { $yr = 2000; }
else { $yr = 1900; }
$line = sprintf ("%.2d-%.2d-%d.%.2d:%.2d:%.2d %s %s\n",
$mon + 1, $mday, $year + $yr, $hour, $min, $sec,$$,$str);
print LOG "$line";
}
print STDOUT "$str\n";
}
# Make a connection to a IMAP host
sub connectToHost {
my $host = shift;
my $conn = shift;
Log("Connecting to $host") if $debug;
($host,$port) = split(/:/, $host);
$port = 143 unless $port;
# We know whether to use SSL for ports 143 and 993. For any
# other ones we'll have to figure it out.
$mode = sslmode( $host, $port );
if ( $mode eq 'SSL' ) {
unless( $ssl_installed == 1 ) {
warn("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
Log("You must have openSSL and IO::Socket::SSL installed to use an SSL connection");
exit;
}
Log("Attempting an SSL connection") if $debug;
$$conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET,
);
unless ( $$conn ) {
$error = IO::Socket::SSL::errstr();
Log("Error connecting to $host: $error");
return 0;
}
} else {
# Non-SSL connection
Log("Attempting a non-SSL connection") if $debug;
$$conn = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
);
unless ( $$conn ) {
Log("Error connecting to $host:$port: $@");
return 0;
}
}
Log("Connected to $host on port $port") if $debug;
return 1;
}
# trim
#
# remove leading and trailing spaces from a string
sub trim {
local (*string) = @_;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return;
}
# login
#
# login in at the source host with the user's name and password
#
sub login {
my $user = shift;
my $pwd = shift;
my $conn = shift;
if ( $pwd =~ /^oauth2:(.+)/i ) {
$token = $1;
Log("password is an OAUTH2 token");
$status = login_xoauth2( $user, $token, $conn );
return $status;
}
sendCommand ($conn, "1 LOGIN $user $pwd");
while (1) {
readResponse ( $conn );
if ($response =~ /^1 OK/i) {
last;
}
elsif ($response =~ /1 NO/) {
Log ("unexpected LOGIN response: $response");
return 0;
}
}
Log("Logged in as $user") if $debug;
return 1;
}
# login_xoauth2
#
# login in at the source host with the user's name and an XOAUTH2 token.
#
sub login_xoauth2 {
my $user = shift;
my $token = shift;
my $conn = shift;
# Do an AUTHENTICATE = XOAUTH2 login
$login_str = encode_base64("user=". $user ."\x01auth=Bearer ". $token ."\x01\x01", '');
sendCommand ($conn, "1 AUTHENTICATE XOAUTH2 $login_str" );
my $loops;
while (1) {
readResponse ( $conn );
if ( $response =~ /^\+ (.+)/ ) {
$error = decode_base64( $1 );
Log("XOAUTH authentication as $user failed: $error");
return 0;
}
last if $response =~ /^1 OK/;
if ($response =~ /^1 NO|^1 BAD|^\* BYE|failed/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
$last if $loops++ > 5;
}
Log("login complete") if $debug;
return 1;
}
# logout
#
# log out from the host
#
sub logout {
my $conn = shift;
undef @response;
sendCommand ($conn, "1 LOGOUT");
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected LOGOUT response: $response");
last;
}
}
close $conn;
return;
}
# getMailboxList
#
# get a list of the user's mailboxes from the source host
#
sub getMailboxList {
my $user = shift;
my $conn = shift;
my @mbxs;
# Get a list of the user's mailboxes
#
if ( $mbxList ) {
# The user has supplied a list of mailboxes so only processes
# the ones in that list
@mbxs = split(/,/, $mbxList);
for $i (0..$#mbxs ) {
$mbxs[$i] =~ s/^\s+//;
$mbxs[$i] =~ s/s+$//;
}
return @mbxs;
}
if ($debugMode) { Log("Get list of user's mailboxes",2); }
sendCommand ($conn, "1 LIST \"\" *");
undef @response;
while ( 1 ) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
last;
}
elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
return 0;
}
}
%nosel_mbxs = ();
undef @mbxs;
for $i (0 .. $#response) {
# print STDERR "$response[$i]\n";
$response[$i] =~ s/\s+/ /;
($dmy,$mbx) = split(/"\/"/,$response[$i]);
$mbx =~ s/^\s+//; $mbx =~ s/\s+$//;
$mbx =~ s/"//g;
if ($response[$i] =~ /NOSELECT/i) {
$nosel_mbxs{"$mbx"} = 1;
}
if (($mbx =~ /^\#/) && ($user ne 'anonymous')) {
# Skip public mbxs unless we are migrating them
next;
}
if ($mbx =~ /^\./) {
# Skip mailboxes starting with a dot
next;
}
push ( @mbxs, $mbx ) if $mbx ne '';
}
if ( $mbxList ) {
# The user has supplied a list of mailboxes so only processes
# those
@mbxs = split(/,/, $mbxList);
}
return @mbxs;
}
# getDeletedMsgs
#
# Get a list of deleted messages in the indicated mailbox on
# the source host
#
sub getDeletedMsgs {
my $mailbox = shift;
my $msgs = shift;
my $conn = shift;
my $seen;
my $empty;
my $msgnum;
@$msgs = ();
trim( *mailbox );
sendCommand ($conn, "1 SELECT \"$mailbox\"");
undef @response;
$empty=0;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
} elsif ( $response =~ / 0 EXISTS/i ) {
$empty = 1;
} elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
print STDERR "Error: $response\n";
return 0;
}
return 0 if $response =~ /^1 NO/;
}
return if $empty;
sendCommand ( $conn, "1 FETCH 1:* (uid flags internaldate body[header.fields (Message-ID Subject)])");
undef @response;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
}
elsif ( $response =~ /Broken pipe|Connection reset by peer/i ) {
Log("Fetch from $mailbox: $response");
return 0;
}
}
# Get a list of the msgs in the mailbox
#
undef @msgs;
undef $flags;
for $i (0 .. $#response) {
$seen=0;
$_ = $response[$i];
last if /OK FETCH complete/;
if ( $response[$i] =~ /FETCH \(UID / ) {
$response[$i] =~ /\* ([^FETCH \(UID]*)/;
$msgnum = $1;
}
if ($response[$i] =~ /FLAGS/) {
# Get the list of flags
$deleted = 0;
$response[$i] =~ /FLAGS \(([^\)]*)/;
$flags = $1;
$deleted = 1 if $flags =~ /Deleted/i;
}
if ( $response[$i] =~ /INTERNALDATE ([^\)]*)/ ) {
$response[$i] =~ /INTERNALDATE ([^BODY]*)/i;
$date = $1;
$date =~ s/"//g;
}
if ( $response[$i] =~ /^Subject:/ ) {
$response[$i] =~ /Subject: (.+)/;
$subject = $1;
}
if ( $response[$i] =~ /^Message-Id:/ ) {
($label,$msgid) = split(/: /, $response[$i]);
trim(*msgid);
$msgid =~ s/^\<//;
$msgid =~ s/\>$//;
push( @$msgs, $msgnum ) if $deleted;
}
}
}
# getDeletedMsgs
#
# Get a list of deleted messages in the indicated mailbox on
# the source host
#
sub OLD_getDeletedMsgs {
my $mailbox = shift;
my $msgs = shift;
my $conn = shift;
my $seen;
my $empty;
my $msgnum;
trim( *mailbox );
sendCommand ($conn, "1 SELECT \"$mailbox\"");
undef @response;
$empty=0;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
} elsif ( $response =~ / 0 EXISTS/i ) {
$empty = 1;
} elsif ( $response !~ /^\*/ ) {
Log ("unexpected response: $response");
print STDERR "Error: $response\n";
return 0;
}
return 0 if $response =~ /^1 NO/;
}
return if $empty;
sendCommand ( $conn, "1 FETCH 1:* (uid flags internaldate body[header.fields (Message-ID Subject)])");
undef @response;
while ( 1 ) {
readResponse ( $conn );
if ( $response =~ /^1 OK/i ) {
# print STDERR "response $response\n";
last;
}
elsif ( $response =~ /Broken pipe|Connection reset by peer/i ) {
Log("Fetch from $mailbox: $response");
return 0;
}
}
# Get a list of the msgs in the mailbox
#
undef @msgs;
undef $flags;
for $i (0 .. $#response) {
$seen=0;
$_ = $response[$i];
last if /OK FETCH complete/;
if ( $response[$i] =~ /FETCH \(UID / ) {
$response[$i] =~ /\* ([^FETCH \(UID]*)/;
$msgnum = $1;
}
if ($response[$i] =~ /FLAGS/) {
# Get the list of flags
$deleted = 0;
$response[$i] =~ /FLAGS \(([^\)]*)/;
$flags = $1;
$deleted = 1 if $flags =~ /Deleted/i;
}
if ( $response[$i] =~ /INTERNALDATE ([^\)]*)/ ) {
$response[$i] =~ /INTERNALDATE ([^BODY]*)/i;
$date = $1;
$date =~ s/"//g;
}
if ( $response[$i] =~ /^Subject:/ ) {
$response[$i] =~ /Subject: (.+)/;
$subject = $1;
}
if ( $response[$i] =~ /^Message-Id:/ ) {
($label,$msgid) = split(/: /, $response[$i]);
trim(*msgid);
$msgid =~ s/^\<//;
$msgid =~ s/\>$//;
push( @$msgs, $msgnum ) if $deleted;
}
}
}
sub fetchMsg {
my $msgnum = shift;
my $mbx = shift;
my $conn = shift;
my $message;
Log(" Fetching msg $msgnum...") if $debug;
sendCommand ($conn, "1 SELECT \"$mbx\"");
while (1) {
readResponse ($conn);
last if ( $response =~ /^1 OK/i );
return 0 if $response =~ /^1 NO/;
}
sendCommand( $conn, "1 FETCH $msgnum (rfc822)");
while (1) {
readResponse ($conn);
if ( $response =~ /^1 OK/i ) {
$size = length($message);
last;
}
elsif ($response =~ /message number out of range/i) {
Log ("Error fetching uid $uid: out of range",2);
$stat=0;
last;
}
elsif ($response =~ /Bogus sequence in FETCH/i) {
Log ("Error fetching uid $uid: Bogus sequence in FETCH",2);
$stat=0;
last;
}
elsif ( $response =~ /message could not be processed/i ) {
Log("Message could not be processed, skipping it ($user,msgnum $msgnum,$destMbx)");
push(@errors,"Message could not be processed, skipping it ($user,msgnum $msgnum,$destMbx)");
$stat=0;
last;
}
elsif
($response =~ /^\*\s+$msgnum\s+FETCH\s+\(.*RFC822\s+\{[0-9]+\}/i) {
($len) = ($response =~ /^\*\s+$msgnum\s+FETCH\s+\(.*RFC822\s+\{([0-9]+)\}/i);
$cc = 0;
$message = "";
while ( $cc < $len ) {
$n = 0;
$n = read ($conn, $segment, $len - $cc);
if ( $n == 0 ) {
Log ("unable to read $len bytes");
return 0;
}
$message .= $segment;
$cc += $n;
}
}
}
return $message;
}
sub usage {
print STDOUT "usage:\n";
print STDOUT " trash.pl -S sourceHost/sourceUser/sourcePassword\n";
print STDOUT " Optional arguments:\n";
print STDOUT " -d debug\n";
print STDOUT " -v verbose\n";
print STDOUT " -I log IMAP commands and responses\n";
print STDOUT " -t <trash mailbox name>\n";
print STDOUT " -e empty trash mailbox\n";
print STDOUT " -L <logfile>\n";
print STDOUT " -m <mailbox list> (eg \"Inbox, Drafts, Notes\". Default is all mailboxes)\n";
print STDOUT " -a <admin_user:admin_password>\n";
exit;
}
sub processArgs {
if ( !getopts( "dvS:L:m:ht:ei:a:I" ) ) {
usage();
}
($sourceHost,$sourceUser,$sourcePwd) = split(/\//, $opt_S);
$userList = $opt_i;
$mbxList = $opt_m;
$logfile = $opt_L;
$trash = $opt_t;
$admin_user = $opt_a;
Log("Admin user:" . $admin_user ) if $verbose;
$emptyTrash = 1 if $opt_e;
$debug = 1 if $opt_d;
$verbose = 1 if $opt_v;
$showIMAP = 1 if $opt_I;
usage() if $opt_h;
$trash = 'Trash' if !$trash;
if ( $userList ) {
if ( !open(F, "<$userList") ) {
Log("Error opening userlist $userList: $!");
exit;
}
while( <F> ) {
chomp;
s/^\s+//;
next if /^#/;
push( @users, $_ );
}
close F;
} else {
push( @users, "$sourceUser $sourcePwd" );
}
if ( $admin_user ) {
$admin_user =~ /(.+):(.+)/;
$admin_user = $1;
$admin_pwd = $2;
}
}
sub expungeMbx {
my $mbx = shift;
my $conn = shift;
Log(" Purging mailbox $mbx") if $debug;
sendCommand ($conn, "1 SELECT \"$mbx\"");
while (1) {
readResponse ($conn);
last if ( $response =~ /^1 OK/i );
return 0 if $response =~ /^1 NO/;
}
sendCommand ( $conn, "1 EXPUNGE");
$expunged=0;
while (1) {
readResponse ($conn);
$expunged++ if $response =~ /\* (.+) Expunge/i;
last if $response =~ /^1 OK/;
if ( $response =~ /^1 BAD|^1 NO/i ) {
print "Error purging messages: $response\n";
last;
}
}
$totalExpunged += $expunged;
}
sub dieright {
local($sig) = @_;
print STDOUT "caught signal $sig\n";
logout( $src );
exit(-1);
}
sub sigprc {
$SIG{'HUP'} = 'dieright';
$SIG{'INT'} = 'dieright';
$SIG{'QUIT'} = 'dieright';
$SIG{'ILL'} = 'dieright';
$SIG{'TRAP'} = 'dieright';
$SIG{'IOT'} = 'dieright';
$SIG{'EMT'} = 'dieright';
$SIG{'FPE'} = 'dieright';
$SIG{'BUS'} = 'dieright';
$SIG{'SEGV'} = 'dieright';
$SIG{'SYS'} = 'dieright';
$SIG{'PIPE'} = 'dieright';
$SIG{'ALRM'} = 'dieright';
$SIG{'TERM'} = 'dieright';
$SIG{'URG'} = 'dieright';
}
sub moveToTrash {
my $mbx = shift;
my $trash = shift;
my $msglist = shift;
my $conn = shift;
my $moved;
return if $mbx eq $trash;
return if $$msglist eq '';
my @moved = split(/,/, $$msglist);
$moved = scalar @moved;
sendCommand ($conn, "1 COPY $$msglist $trash");
while (1) {
readResponse ( $conn );
last if $response =~ /^1 OK/i;
if ($response =~ /NO/) {
Log("unexpected COPY response: $response");
Log("Please verify that mailbox $trash exists");
return 0;
}
}
Log(" Moved $moved messages from $mbx to $trash");
$total += $moved;
}
# login_plain
#
# login in at the source host with the user's name and password. If provided
# with administrator credential, use them as this eliminates the need for the
# user's password.
#
sub login_plain {
my $user = shift;
my $admin = shift;
my $pwd = shift;
my $conn = shift;
# Do an AUTHENTICATE = PLAIN. If an admin user has been provided then use it.
if ( !$admin ) {
# Log in as the user
$admin = $user
}
$login_str = sprintf("%s\x00%s\x00%s", $user,$admin,$pwd);
$login_str = encode_base64("$login_str", "");
$len = length( $login_str );
#sendCommand ($conn, "1 AUTHENTICATE PLAIN {$len}" );
sendCommand ($conn, "1 AUTHENTICATE PLAIN $login_str" );
#my $loops;
#while (1) {
#readResponse ( $conn );
#last if $response =~ /\+/;
#if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
#Log ("unexpected LOGIN response: $response");
#exit;
#}
#$last if $loops++ > 5;
#}
#sendCommand ($conn, "$login_str" );
my $loops;
while (1) {
readResponse ( $conn );
last if $response =~ /^1 OK/i;
if ($response =~ /^1 NO|^1 BAD|^\* BYE/i) {
Log ("unexpected LOGIN response: $response");
return 0;
}
$last if $loops++ > 5;
}
return 1;
}
sub sslmode {
my $host = shift;
my $port = shift;
my $mode;
Log("CONNEXION SSL") if $verbose;
# Determine whether to make an SSL connection
# to the host. Return 'SSL' if so.
if ( $port == 143 ) {
# Standard non-SSL port
return '';
} elsif ( $port == 993 ) {
# Standard SSL port
return 'SSL';
}
unless ( $ssl_installed ) {
# We don't have SSL installed on this machine
return '';
}
# For any other port we need to determine whether it supports SSL
my $conn = IO::Socket::SSL->new(
Proto => "tcp",
SSL_verify_mode => 0x00,
PeerAddr => $host,
PeerPort => $port,
);
if ( $conn ) {
close( $conn );
$mode = 'SSL';
} else {
$mode = '';
}
return $mode;
}
sub find_deleted_msgs {
my $mbx = shift;
my $msglist = shift;
my $conn = shift;
my $msgnum;
# Issue a SEARCH DELETED command to get a list of messages
# marked for deletion.
$$msglist = '';
Log("SELECT $mbx") if $debug;
sendCommand ( $conn, "1 SELECT \"$mbx\"");
while (1) {
readResponse ($conn);
last if $response =~ /^1 OK/;
return 0 if $response =~ /^1 NO/;
}
Log("Search for $msgid") if $debug;
sendCommand ( $conn, "1 SEARCH DELETED");
while (1) {
readResponse ($conn);
if ( $response =~ /\* SEARCH /i ) {
($dmy, $$msglist) = split(/\* SEARCH /i, $response, 2);
$$msglist =~ s/\s+/,/g;
Log("msglist $$msglist") if $debug;
}
last if $response =~ /^1 OK/;
last if $response =~ /complete/i;
}
}
sub createMbx {
my $mbx = shift;
my $conn = shift;
# Create the mailbox if necessary
sendCommand ($conn, "1 CREATE \"$mbx\"");
while ( 1 ) {
readResponse ($conn);
last if $response =~ /^1 OK/i;
last if $response =~ /already exists/i;
if ( $response =~ /^1 NO|^1 BAD|^\* BYE/ ) {
Log ("Error creating $mbx: $response");
last;
}
if ( $response eq '' or $response =~ /^1 NO/ ) {
Log ("unexpected CREATE response: >$response<");
Log("response is NULL");
resume();
last;
}
}
}
sub mbxExists {
my $mbx = shift;
my $conn = shift;
my $status = 1;
# Determine whether a mailbox exists
sendCommand ($conn, "1 EXAMINE \"$mbx\"");
while (1) {
readResponse ($conn);
last if $response =~ /^1 OK/i;
if ( $response =~ /^1 NO|^1 BAD|^\* BYE/ ) {
$status = 0;
last;
}
}
return $status;
}

23
S/imapservers.shtml Executable file → Normal file
View File

@ -4,7 +4,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" id="TOP"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" id="TOP">
<head> <head>
<title>Imapsync list of 73 imap server software supported (and the few failures)</title> <title>Imapsync list of 75 imap server software applications supported</title>
<meta name="generator" content="Bluefish 2.2.2" /> <meta name="generator" content="Bluefish 2.2.2" />
<meta name="author" content="Gilles LAMIRAL" /> <meta name="author" content="Gilles LAMIRAL" />
<meta name="date" content="2016-04-10T00:24:15+0200" /> <meta name="date" content="2016-04-10T00:24:15+0200" />
@ -27,19 +27,19 @@
<body> <body>
<h1>Imapsync list of imap server softwares supported (and the failures one) <a id="imap_server_success" href="../#TOP"><small>(back to menu)</small></a> <h1>Imapsync list of 75 imap server software applications supported (and the broken ones) <a id="imap_server_success" href="../#TOP"><small>(back to menu)</small></a>
</h1> </h1>
<p>To know weither your IMAP server is a widespread choice, <p>To know whether your IMAP server is a widespread choice,
take a look at <a href="http://openemailsurvey.org/">http://openemailsurvey.org/</a>. take a look at <a href="http://openemailsurvey.org/">http://openemailsurvey.org/</a>.
</p> </p>
<p>Let's start with the long reported <b>success stories</b> list: <b> <p>Let's start with the long reported <b>success stories</b> list: <b>
72 different imap software servers supported!</b><br/> 74 different imap server software tools supported!</b><br/>
[host1] means "source server" and [host2] means "destination server": [host1] means "source server" and [host2] means "destination server":
</p> </p>
<p>Please report to the author (gilles.lamiral@laposte.net) <p>Please report to the author (gilles@lamiral.info)
any success or bad story with any success or bad story with
imapsync and, if you know them, mention the IMAP server imapsync and, if you know them, mention the IMAP server
software names and version on both sides. This will help software names and version on both sides. This will help
@ -63,7 +63,7 @@ imapsync --host1 test1.lamiral.info \
</pre> </pre>
<p>And now the imap servers software imapsync success list:</p> <p>And now the imap servers software imapsync success list:</p>
<ol> <ol>
<li>1und1 H mimap1 84498 [host1], H mibap4 95231 [host1](<a href="http://www.1und1.de/">http://www.1und1.de/</a>)</li> <li>1und1 H mimap1 84498 [host1], H mibap4 95231 [host1](<a href="http://www.1und1.de/">http://www.1und1.de/</a>)</li>
@ -76,6 +76,7 @@ imapsync --host1 test1.lamiral.info \
<li>Atmail 6.x [host1] <a href="https://www.atmail.com/">https://www.atmail.com/</a></li> <li>Atmail 6.x [host1] <a href="https://www.atmail.com/">https://www.atmail.com/</a></li>
<li>Axigen Mail Server Version 8.0.0 (<a href="https://www.axigen.com/">https://www.axigen.com/</a>)</li> <li>Axigen Mail Server Version 8.0.0 (<a href="https://www.axigen.com/">https://www.axigen.com/</a>)</li>
<li>BincImap 1.2.3 (GPL) (<a href="http://www.bincimap.org/">http://www.bincimap.org/</a>)</li> <li>BincImap 1.2.3 (GPL) (<a href="http://www.bincimap.org/">http://www.bincimap.org/</a>)</li>
<li>BlueMind <a href="https://www.bluemind.net/"></a>https://www.bluemind.net/</li>
<li>ClearOS <a href="https://www.clearos.com/">https://www.clearos.com/</a> uses Cyrus as IMAP backend server.</li> <li>ClearOS <a href="https://www.clearos.com/">https://www.clearos.com/</a> uses Cyrus as IMAP backend server.</li>
<li>CommuniGatePro server (Redhat 8.0) (Solaris), CommuniGate Pro 5.2.17[host2] (CentOS 5.4) <li>CommuniGatePro server (Redhat 8.0) (Solaris), CommuniGate Pro 5.2.17[host2] (CentOS 5.4)
(<a href="http://www.communigate.com/">http://www.communigate.com/</a>) </li> (<a href="http://www.communigate.com/">http://www.communigate.com/</a>) </li>
@ -128,6 +129,7 @@ imapsync --host1 test1.lamiral.info \
(<a href="http://en.wikipedia.org/wiki/Oracle_Communications_Messaging_Server">http://en.wikipedia.org/wiki/Oracle_Communications_Messaging_Server</a>) </li> (<a href="http://en.wikipedia.org/wiki/Oracle_Communications_Messaging_Server">http://en.wikipedia.org/wiki/Oracle_Communications_Messaging_Server</a>) </li>
<li>iRedMail, iRedMail imap server software is Dovecot. <a href="http://www.iredmail.org/">http://www.iredmail.org/</a></li> <li>iRedMail, iRedMail imap server software is Dovecot. <a href="http://www.iredmail.org/">http://www.iredmail.org/</a></li>
<li>Kerio 7.2.0P1 [host1] (<a href="http://www.kerio.com/">http://www.kerio.com/</a>) </li> <li>Kerio 7.2.0P1 [host1] (<a href="http://www.kerio.com/">http://www.kerio.com/</a>) </li>
<li>Kopano (<a href="https://kopano.com/">https://kopano.com/</a>) (successor of Zarafa) </li>
<li>Mail2World IMAP4 Server 2.5 [host1] (<a href="http://www.mail2world.com/">http://www.mail2world.com/</a>)</li> <li>Mail2World IMAP4 Server 2.5 [host1] (<a href="http://www.mail2world.com/">http://www.mail2world.com/</a>)</li>
<li><b>MailEnable</b> 4.23 [host1][host2], 4.26 [host1][host2], 5 [host1] <li><b>MailEnable</b> 4.23 [host1][host2], 4.26 [host1][host2], 5 [host1]
(<a href="http://www.mailenable.com/">http://www.mailenable.com/</a>) </li> (<a href="http://www.mailenable.com/">http://www.mailenable.com/</a>) </li>
@ -166,11 +168,12 @@ imapsync --host1 test1.lamiral.info \
(RedHat uses UW like 2003.338rh), v12.264 Solaris 5.7 (OSI Approved) (RedHat uses UW like 2003.338rh), v12.264 Solaris 5.7 (OSI Approved)
(<a href="http://www.washington.edu/imap/">http://www.washington.edu/imap/</a>) </li> (<a href="http://www.washington.edu/imap/">http://www.washington.edu/imap/</a>) </li>
<li>VMS, Imap part of TCP/IP suite of VMS 7.3.2 (<a href="http://h71000.www7.hp.com/openvms/">http://h71000.www7.hp.com/openvms/</a>) </li> <li>VMS, Imap part of TCP/IP suite of VMS 7.3.2 (<a href="http://h71000.www7.hp.com/openvms/">http://h71000.www7.hp.com/openvms/</a>) </li>
<li><b>Yahoo</b> [host1] (<a href="http://www.yahoo.com/">http://www.yahoo.com/</a>) </li> <li>Xeams/Synametrics (<a href="http://www.xeams.com/">http://www.xeams.com/</a>) </li>
<li><b>Yahoo</b> [host1] (<a href="http://www.yahoo.com/">http://www.yahoo.com/</a>) </li>
<li>Zarafa 6,40,0,20653 [host1] (<a href="http://www.zarafa.com/">http://www.zarafa.com/</a>) </li> <li>Zarafa 6,40,0,20653 [host1] (<a href="http://www.zarafa.com/">http://www.zarafa.com/</a>) </li>
<li>Zarafa ZCP 7.1.4 IMAP Gateway [host2]</li> <li>Zarafa ZCP 7.1.4 IMAP Gateway [host2]</li>
<li><b>Zimbra-IMAP</b> 3.0.1 GA 160, 3.1.0 Build 279, 4.0.5, 4.5.2, 4.5.6, <li><b>Zimbra-IMAP</b> 3.0.1 GA 160, 3.1.0 Build 279, 4.0.5, 4.5.2, 4.5.6,
Zimbra 5.0.24_GA_3356.RHEL4 [host1], 5.5, 6.x Zimbra 5.0.24_GA_3356.RHEL4 [host1], 5.5, any 6.x, any 8.x
(<a href="http://www.zimbra.com/">http://www.zimbra.com/</a>) </li> (<a href="http://www.zimbra.com/">http://www.zimbra.com/</a>) </li>
<li>Zentyal (Zinc) [host1] (<a href="http://www.zentyal.org/">http://www.zentyal.org/</a>) </li> <li>Zentyal (Zinc) [host1] (<a href="http://www.zentyal.org/">http://www.zentyal.org/</a>) </li>
@ -178,7 +181,7 @@ imapsync --host1 test1.lamiral.info \
<p>Let's finish with reported <b>failure stories</b> over the past.<br/> <p>Let's finish with reported <b>failure stories</b> over the past.<br/>
Maybe <b>new imapsync releases can run successfully with them</b>.<br/> Maybe <b>new imapsync releases can run successfully with them</b>.<br/>
Don't hesitate to have a try, It's been a long time since last failure occured, Don't hesitate to have a try, It's been a long time since last failure occurred,
I will help you and make efforts to switch them to the success list, I will help you and make efforts to switch them to the success list,
that's my job. that's my job.
</p> </p>
@ -221,7 +224,7 @@ alt="Viewable With Any Browser" />
<!--#config timefmt="%D" --> <!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" --> <!--#config timefmt="%A %B %d, %Y" -->
<b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b> <b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: imapservers.shtml,v 1.32 2017/09/11 03:04:46 gilles Exp gilles $)<br/> ($Id: imapservers.shtml,v 1.36 2018/04/10 00:26:50 gilles Exp gilles $)<br/>
<a href="#TOP">Top of the page</a> <a href="#TOP">Top of the page</a>
</p> </p>

View File

@ -1,63 +1,63 @@
1373 Etats-Unis______________ 23.64 % 24 % 1 1445 Etats-Unis______________ 23.15 % 23 % 1
1111 Allemagne_______________ 19.13 % 43 % 2 1206 Allemagne_______________ 19.32 % 42 % 2
521 Royaume-Uni_____________ 8.97 % 52 % 3 560 Royaume-Uni_____________ 8.97 % 51 % 3
343 Italie__________________ 5.90 % 58 % 4 379 Italie__________________ 6.07 % 58 % 4
282 France__________________ 4.85 % 62 % 5 303 France__________________ 4.85 % 62 % 5
244 Canada__________________ 4.20 % 67 % 6 261 Canada__________________ 4.18 % 67 % 6
233 Pays-Bas________________ 4.01 % 71 % 7 252 Pays-Bas________________ 4.04 % 71 % 7
231 Suisse__________________ 3.98 % 75 % 8 251 Suisse__________________ 4.02 % 75 % 8
196 Australie_______________ 3.37 % 78 % 9 207 Australie_______________ 3.32 % 78 % 9
128 Autriche________________ 2.20 % 80 % 10 142 Autriche________________ 2.27 % 80 % 10
120 Espagne_________________ 2.07 % 82 % 11 131 Espagne_________________ 2.10 % 82 % 11
97 Belgique________________ 1.67 % 84 % 12 102 Belgique________________ 1.63 % 84 % 12
87 Suede___________________ 1.50 % 85 % 13 94 Suede___________________ 1.51 % 85 % 13
78 Danemark________________ 1.34 % 87 % 14 79 Danemark________________ 1.27 % 87 % 14
55 Bresil__________________ 0.95 % 88 % 15 61 Bresil__________________ 0.98 % 88 % 15
47 Pologne_________________ 0.81 % 89 % 16 55 Pologne_________________ 0.88 % 89 % 16
45 Norvege_________________ 0.77 % 89 % 17 47 Norvege_________________ 0.75 % 89 % 17
37 Republique_tcheque______ 0.64 % 90 % 18 46 Republique_tcheque______ 0.74 % 90 % 18
37 Finlande________________ 0.64 % 91 % 19 44 Finlande________________ 0.70 % 91 % 19
31 Russie__________________ 0.53 % 91 % 20 33 Hongrie_________________ 0.53 % 91 % 20
29 Hongrie_________________ 0.50 % 92 % 21 31 Russie__________________ 0.50 % 92 % 21
28 Nouvelle-Zelande________ 0.48 % 92 % 22 29 Nouvelle-Zelande________ 0.46 % 92 % 22
27 Japon___________________ 0.46 % 93 % 23 27 Japon___________________ 0.43 % 93 % 23
25 ________________________ 0.43 % 93 % 24 25 ________________________ 0.40 % 93 % 24
23 Irlande_________________ 0.40 % 93 % 25 24 Portugal________________ 0.38 % 93 % 25
22 Grece___________________ 0.38 % 94 % 26 23 Irlande_________________ 0.37 % 94 % 26
21 Portugal________________ 0.36 % 94 % 27 23 Grece___________________ 0.37 % 94 % 27
20 Afrique_du_Sud__________ 0.34 % 95 % 28 22 Afrique_du_Sud__________ 0.35 % 95 % 28
19 Hong-Kong_______________ 0.33 % 95 % 29 20 Hong-Kong_______________ 0.32 % 95 % 29
17 Slovaquie_______________ 0.29 % 95 % 30 19 Inde____________________ 0.30 % 95 % 30
17 Inde____________________ 0.29 % 95 % 31 17 Slovaquie_______________ 0.27 % 95 % 31
17 Argentine_______________ 0.29 % 96 % 32 17 Mexique_________________ 0.27 % 96 % 32
16 Mexique_________________ 0.28 % 96 % 33 17 Argentine_______________ 0.27 % 96 % 33
15 Malaisie________________ 0.26 % 96 % 34 16 Roumanie________________ 0.26 % 96 % 34
15 Chili___________________ 0.26 % 97 % 35 16 Malaisie________________ 0.26 % 97 % 35
14 Singapour_______________ 0.24 % 97 % 36 16 Chili___________________ 0.26 % 97 % 36
14 Luxembourg______________ 0.24 % 97 % 37 15 Chine___________________ 0.24 % 97 % 37
14 Chine___________________ 0.24 % 97 % 38 14 Slovenie________________ 0.22 % 97 % 38
13 Roumanie________________ 0.22 % 97 % 39 14 Singapour_______________ 0.22 % 97 % 39
12 Slovenie________________ 0.21 % 98 % 40 14 Luxembourg______________ 0.22 % 98 % 40
11 Israel__________________ 0.19 % 98 % 41 12 Israel__________________ 0.19 % 98 % 41
10 Emirats_Arabes_Unis_____ 0.17 % 98 % 42 10 Emirats_Arabes_Unis_____ 0.16 % 98 % 42
9 Lettonie________________ 0.15 % 98 % 43 9 Lettonie________________ 0.14 % 98 % 43
7 Croatie_________________ 0.12 % 98 % 44 7 Croatie_________________ 0.11 % 98 % 44
6 Thailande_______________ 0.10 % 98 % 45 6 Thailande_______________ 0.10 % 98 % 45
6 Islande_________________ 0.10 % 99 % 46 6 Malte___________________ 0.10 % 98 % 46
5 Malte___________________ 0.09 % 99 % 47 6 Islande_________________ 0.10 % 99 % 47
5 Estonie_________________ 0.09 % 99 % 48 6 Estonie_________________ 0.10 % 99 % 48
5 Egypte__________________ 0.09 % 99 % 49 5 Lituanie________________ 0.08 % 99 % 49
4 Turquie_________________ 0.07 % 99 % 50 5 Egypte__________________ 0.08 % 99 % 50
4 Indonesie_______________ 0.07 % 99 % 51 4 Turquie_________________ 0.06 % 99 % 51
4 Chypre__________________ 0.07 % 99 % 52 4 Serbie__________________ 0.06 % 99 % 52
4 Bulgarie________________ 0.07 % 99 % 53 4 Ireland_________________ 0.06 % 99 % 53
3 Venezuela_______________ 0.05 % 99 % 54 4 Indonesie_______________ 0.06 % 99 % 54
3 Serbie__________________ 0.05 % 99 % 55 4 Chypre__________________ 0.06 % 99 % 55
3 Philippines_____________ 0.05 % 99 % 56 4 Bulgarie________________ 0.06 % 99 % 56
3 Lituanie________________ 0.05 % 99 % 57 3 Venezuela_______________ 0.05 % 99 % 57
3 Ireland_________________ 0.05 % 99 % 58 3 Uruguay_________________ 0.05 % 99 % 58
2 Vietnam_________________ 0.03 % 99 % 59 3 Philippines_____________ 0.05 % 99 % 59
2 Uruguay_________________ 0.03 % 99 % 60 2 Vietnam_________________ 0.03 % 99 % 60
2 Ukraine_________________ 0.03 % 99 % 61 2 Ukraine_________________ 0.03 % 99 % 61
2 Perou___________________ 0.03 % 99 % 62 2 Perou___________________ 0.03 % 99 % 62
2 Nouvelle-Caledonie______ 0.03 % 99 % 63 2 Nouvelle-Caledonie______ 0.03 % 99 % 63
@ -68,25 +68,27 @@
1 Taiwan__________________ 0.02 % 100 % 68 1 Taiwan__________________ 0.02 % 100 % 68
1 Senegal_________________ 0.02 % 100 % 69 1 Senegal_________________ 0.02 % 100 % 69
1 Saint_Christophe-Nevis-Anguilla__ 0.02 % 100 % 70 1 Saint_Christophe-Nevis-Anguilla__ 0.02 % 100 % 70
1 Qatar___________________ 0.02 % 100 % 71 1 Republique_d'Azerbaidjan__ 0.02 % 100 % 71
1 Panama__________________ 0.02 % 100 % 72 1 Qatar___________________ 0.02 % 100 % 72
1 Nigeria_________________ 0.02 % 100 % 73 1 Panama__________________ 0.02 % 100 % 73
1 Namibie_________________ 0.02 % 100 % 74 1 Nigeria_________________ 0.02 % 100 % 74
1 Mongolie________________ 0.02 % 100 % 75 1 Namibie_________________ 0.02 % 100 % 75
1 Monaco__________________ 0.02 % 100 % 76 1 Mongolie________________ 0.02 % 100 % 76
1 Moldavie________________ 0.02 % 100 % 77 1 Monaco__________________ 0.02 % 100 % 77
1 Maldives________________ 0.02 % 100 % 78 1 Moldavie________________ 0.02 % 100 % 78
1 Koweit__________________ 0.02 % 100 % 79 1 Maroc___________________ 0.02 % 100 % 79
1 Jordanie________________ 0.02 % 100 % 80 1 Maldives________________ 0.02 % 100 % 80
1 Jamaique________________ 0.02 % 100 % 81 1 Koweit__________________ 0.02 % 100 % 81
1 Iles_Vierges_britanniques__ 0.02 % 100 % 82 1 Jordanie________________ 0.02 % 100 % 82
1 Grenade_________________ 0.02 % 100 % 83 1 Jamaique________________ 0.02 % 100 % 83
1 Coree_du_Sud____________ 0.02 % 100 % 84 1 Iles_Vierges_britanniques__ 0.02 % 100 % 84
1 Colombie________________ 0.02 % 100 % 85 1 Grenade_________________ 0.02 % 100 % 85
1 Cameroun________________ 0.02 % 100 % 86 1 Coree_du_Sud____________ 0.02 % 100 % 86
1 Burkina_Faso____________ 0.02 % 100 % 87 1 Colombie________________ 0.02 % 100 % 87
1 Bosnie-Herzegovine______ 0.02 % 100 % 88 1 Cameroun________________ 0.02 % 100 % 88
1 Bahrein_________________ 0.02 % 100 % 89 1 Burkina_Faso____________ 0.02 % 100 % 89
1 Arabie_Saoudite_________ 0.02 % 100 % 90 1 Bosnie-Herzegovine______ 0.02 % 100 % 90
1 Albanie_________________ 0.02 % 100 % 91 1 Bahrein_________________ 0.02 % 100 % 91
TOTAL = 5809 sales 268740 EUR over 91 countries on Thu Sep 7 01:46:18 CEST 2017 1 Arabie_Saoudite_________ 0.02 % 100 % 92
1 Albanie_________________ 0.02 % 100 % 93
TOTAL = 6242 sales 294171 EUR over 93 countries on Sun May 6 01:20:26 CEST 2018

76
S/news.shtml Executable file → Normal file
View File

@ -39,7 +39,7 @@ next and previous releases <a href="../#TOP" id="latest"><small>(back to menu)
<!-- <!--
<ul> <ul>
<li><b>1.824</b></li> <li><b>1.882</b></li>
<li><b>Enhancement</b>: </li> <li><b>Enhancement</b>: </li>
<li><b>Enhancement</b>: </li> <li><b>Enhancement</b>: </li>
<li><b>Enhancement</b>: </li> <li><b>Enhancement</b>: </li>
@ -53,21 +53,64 @@ next and previous releases <a href="../#TOP" id="latest"><small>(back to menu)
<li><b>Bug fix</b>: </li> <li><b>Bug fix</b>: </li>
<li><b>Bug fix</b>: </li> <li><b>Bug fix</b>: </li>
<li><b>Refactoring</b>: Removed most of the perlcrit (Severity: 3) Regular expression without "/x" flag.</li> <li><b>Refactoring</b>: </li>
<li><b>Refactoring</b>: </li> <li><b>Refactoring</b>: </li>
<li><b>Refactoring</b>: </li> <li><b>Refactoring</b>: </li>
<li><b>Refactoring</b>: </li> <li><b>Refactoring</b>: </li>
<li><b>Security</b>: </li> <li><b>Security</b>: </li>
<li><b>Dependency</b>: </li> <li><b>Dependency removed</b>: </li>
<li><b>Dependency added</b>: </li> <li><b>Dependency added</b>: </li>
</ul> </ul>
--> -->
<ul>
<li><b>1.882</b> (2018/05/06) On the road to a proxy mode! (not done yet)</li>
<li><b>Enhancement</b>: Added option --nocheckfoldersexist ( Default is like --checkfoldersexist )</li>
<li><b>Enhancement</b>: Added option --noresyncflags : Do not resync flags for already transfered messages.
May be useful when a user has already started to play with its host2 account.</li>
<li><b>Enhancement</b>: Option --abort now creates a log too, in order to see if imapsync ended by signal comes from option --abort or something else.</li>
<li><b>Enhancement</b>: Added option --sigexit; For example --sigexit QUIT --sigexit TERM to exit when receiving QUIT or TERM signals.<br>
Added option --sigreconnect. For example --sigreconnect INT to reconnect to both imap servers when receiving INT signal.<br>
Added option --sigignore. For example --sigignore TERM to "ignore" the TERM signal. In fact print stats during the sync.<br>
Default is like: --sigexit QUIT --sigexit TERM --sigreconnect INT
</li>
<li><b>Enhancement</b>: Moved the hostname printing at first line. The goal is for clarity when in proxy mode.<br>
Added free RAM info in the banner.<br>
</li>
<li><b>Enhancement</b>: When using sleeping behavior, a signal USR1 toggles sleep from 2s to 0s (back to 2s with on next USR1 signal). Unix only.</li>
<li><b>Usability</b>: Detect extra arguments. Meaning usually a quoting issue in the command line or that options are not well parsed.</li>
<li><b>Usability</b>: Added inline documentation about --releasecheck and --noreleasecheck
Default upstream is still --releasecheck. Just a line to change to have --noreleasecheck by default (as before)</li>
<li><b>Usability</b>: Added inline advice to resync after an end commanded by a TERM or QUIT signal.</li>
<li><b>Bug fix</b>: Fixed sub epoch() to allow that kind of silly INTERNALDATE 00-Jan-0000 00:00:00 +0000
(Thanks to IBM Domino...)</li>
<li><b>Bug fix</b>: --releasecheck activated was hardcoded in cgi context. Now it depends on the default behavior chosen.
Bug pending. Still have to fix --releasecheck on with --help</li>
<li><b>Bug fix</b>: Added \t\r\n characters to be replaced by character _ in sub filter_forbidden_characters()</li>
<li><b>Bug fix</b>: fixes to pass --tests under root user.</li>
<li><b>CGI context</b>: Added SERVER_SOFTWARE and SERVER_PORT info.</li>
<li><b>CGI context</b>: Added free RAM, total RAM and hostname in the status.</li>
<li><b>CGI context</b>: Reduced the loadavg info in the header status.</li>
<li><b>Refactoring</b>: Fixed some perlcritics level 4.</li>
<li><b>Refactoring</b>: Deglobalized several global variables.</li>
<li><b>Dependency added</b>: Perl module Regex::Common</li>
</ul>
<ul> <ul>
<li><b>1.836</b> More secure by default, ssl or tls activation!</li> <li><b>1.836</b> (2017/09/05) More secure by default, ssl or tls activation!</li>
<li><b>Enhancement</b>: An <a href="https://hub.docker.com/r/gilleslamiral/imapsync/"><b>Imapsync Docker image</b></a> available!</li> <li><b>Enhancement</b>: An <a href="https://hub.docker.com/r/gilleslamiral/imapsync/"><b>Imapsync Docker image</b></a> available!</li>
@ -84,6 +127,9 @@ next and previous releases <a href="../#TOP" id="latest"><small>(back to menu)
<li><b>Enhancement</b>: Added <tt>--office1</tt> and <tt>--office2</tt> to simplify Office 365 options setting. <li><b>Enhancement</b>: Added <tt>--office1</tt> and <tt>--office2</tt> to simplify Office 365 options setting.
It sets parameters suggested in the <a href="../FAQ.d/FAQ.Exchange.txt">Exchange/Office365 FAQ</a>.</li> It sets parameters suggested in the <a href="../FAQ.d/FAQ.Exchange.txt">Exchange/Office365 FAQ</a>.</li>
<li><b>Enhancement</b>: Added <tt>--exchange1</tt> and <tt>--exchange2</tt> to simplify Exchange options setting.
It sets parameters suggested in the <a href="../FAQ.d/FAQ.Exchange.txt">Exchange FAQ</a>.</li>
<li><b>Enhancement</b>: Added <tt>--domino1</tt> and <tt>--domino2</tt> to simplify Domino options setting. <li><b>Enhancement</b>: Added <tt>--domino1</tt> and <tt>--domino2</tt> to simplify Domino options setting.
It sets parameters suggested in the <a href="../FAQ.d/FAQ.Domino.txt">Domino FAQ</a>.</li> It sets parameters suggested in the <a href="../FAQ.d/FAQ.Domino.txt">Domino FAQ</a>.</li>
@ -157,7 +203,7 @@ In cgi context, ie online, exact same credentials are needed in order to really
<ul> <ul>
<li><b>1.727</b> https website and CGI on the way!</li> <li><b>1.727</b> (2016/08/19) https website and CGI on the way!</li>
<li><b>Security</b>: Thanks to free and easy <b>letsencrypt</b>, <li><b>Security</b>: Thanks to free and easy <b>letsencrypt</b>,
@ -210,7 +256,7 @@ Started as a copy of Luke Ross Getopt::Long::CGI</li>
</ul> </ul>
<ul> <ul>
<li><b>1.684</b> Small changes, bugfixes</li> <li><b>1.684</b> (2016/03/17) Small changes, bugfixes</li>
<li><b>Bug fix</b>: Imapsync.exe updated to Mail-IMAPClient-3.38 (3.37 had a bug with credentials containing special characters)</li> <li><b>Bug fix</b>: Imapsync.exe updated to Mail-IMAPClient-3.38 (3.37 had a bug with credentials containing special characters)</li>
@ -225,7 +271,7 @@ in ssl or tls mode. Was due to "'SSL_version' => undef".</li>
<ul> <ul>
<li><b>1.678</b> <b>Improved website!</b> (I hope...)</li> <li><b>1.678</b> (2016/01/21) <b>Improved website!</b> (I hope...)</li>
<li><b>Enhancement</b>: Added <b><tt>--sslargs1</tt></b> and <b><tt>--sslargs2</tt></b> to pass any ssl parameter for host1 or host2 connection. <li><b>Enhancement</b>: Added <b><tt>--sslargs1</tt></b> and <b><tt>--sslargs2</tt></b> to pass any ssl parameter for host1 or host2 connection.
Example: <tt>--sslargs1 SSL_verify_mode=1 --sslargs1 SSL_version=SSLv3</tt></li> Example: <tt>--sslargs1 SSL_verify_mode=1 --sslargs1 SSL_version=SSLv3</tt></li>
<li><b>Enhancement</b>: Added <tt>--timeout1 int</tt> and <tt>--timeout2 int</tt> in seconds (<tt>--timeout int</tt> still available to set both with the same value)</li> <li><b>Enhancement</b>: Added <tt>--timeout1 int</tt> and <tt>--timeout2 int</tt> in seconds (<tt>--timeout int</tt> still available to set both with the same value)</li>
@ -248,7 +294,7 @@ without using <tt>PERL_LWP_ENV_PROXY=1</tt></li>
</ul> </ul>
<ul> <ul>
<li><b>1.670</b> Folders <b>mapping made easy</b> with <b>--automap</b></li> <li><b>1.670</b> (2015/12/03) Folders <b>mapping made easy</b> with <b>--automap</b></li>
<li><b>Enhancement</b>: Added option <b><tt>--automap</tt></b> that guesses folders mapping, <li><b>Enhancement</b>: Added option <b><tt>--automap</tt></b> that guesses folders mapping,
for folders like "Sent", "Junk", "Drafts", "All", "Archive", "Flagged". for folders like "Sent", "Junk", "Drafts", "All", "Archive", "Flagged".
@ -310,7 +356,7 @@ without using <tt>PERL_LWP_ENV_PROXY=1</tt></li>
</ul> </ul>
<ul> <ul>
<li><b>1.644</b> Mac OS X standalone binary provided!</li> <li><b>1.644</b> (2015/07/17) Mac OS X standalone binary provided!</li>
<li><b>Enhancement</b>: Mac OS X standalone binary called <tt>imapsync_bin_Darwin</tt></li> <li><b>Enhancement</b>: Mac OS X standalone binary called <tt>imapsync_bin_Darwin</tt></li>
<li><b>Enhancement</b>: Added option <tt>--subfolder2 SUB</tt> Move whole host1 folders hierarchy under folder SUB.</li> <li><b>Enhancement</b>: Added option <tt>--subfolder2 SUB</tt> Move whole host1 folders hierarchy under folder SUB.</li>
@ -326,7 +372,7 @@ Need a patched Mail::IMAPClient 3.35 in <tt>sub fetch_hash()</tt></li>
</ul> </ul>
<ul> <ul>
<li><b>1.636</b></li> <li><b>1.636</b> (2015/03/31)</li>
<li><b>Enhancement</b>: Added errors dump listing at the end, before last folder sizes or the statistics. Turned on by default. Use <tt>--noerrorsdump</tt> to avoid it.</li> <li><b>Enhancement</b>: Added errors dump listing at the end, before last folder sizes or the statistics. Turned on by default. Use <tt>--noerrorsdump</tt> to avoid it.</li>
<li><b>Enhancement</b>: Added <tt>--maxlinelengthcmd</tt> that will be called upon when a line over <tt>--maxlinelength</tt> value is detected. </li> <li><b>Enhancement</b>: Added <tt>--maxlinelengthcmd</tt> that will be called upon when a line over <tt>--maxlinelength</tt> value is detected. </li>
<li><b>Enhancement</b>: Exchange maxlinelength issue fixed with <tt>--maxlinelengthcmd 'reformime -r7'</tt> on Linux. <li><b>Enhancement</b>: Exchange maxlinelength issue fixed with <tt>--maxlinelengthcmd 'reformime -r7'</tt> on Linux.
@ -357,7 +403,7 @@ HMailServer replies two lines with <tt>--useheader "Message-Id" --useheader "Mes
<ul> <ul>
<li><b>1.607</b> Folders shown also in utf8.</li> <li><b>1.607</b> (2014/11/14) Folders shown also in utf8.</li>
<li><b>Caveat to upgrade on Unix!</b>: New <b>Unicode::String</b> Perl module dependency, for utf8 output. See the <a href="../INSTALL">INSTALL</a> file.</li> <li><b>Caveat to upgrade on Unix!</b>: New <b>Unicode::String</b> Perl module dependency, for utf8 output. See the <a href="../INSTALL">INSTALL</a> file.</li>
<li><b>Enhancement</b>: Added --skipemptyfolders to skip syncing empty host1 folders. They are not created on host2.</li> <li><b>Enhancement</b>: Added --skipemptyfolders to skip syncing empty host1 folders. They are not created on host2.</li>
<li><b>Enhancement</b>: Windows exe now uses IO::SSL 2.002 instead of 1.98 (is it really an enhancement?).</li> <li><b>Enhancement</b>: Windows exe now uses IO::SSL 2.002 instead of 1.98 (is it really an enhancement?).</li>
@ -374,14 +420,14 @@ HMailServer replies two lines with <tt>--useheader "Message-Id" --useheader "Mes
</ul> </ul>
<ul> <ul>
<li><b>1.597</b> Small things</li> <li><b>1.597</b> (2014/10/06) Small things</li>
<li><b>Enhancement</b>: Added --nomixfolders to avoid merging folders that are considered different on host1 but the same on destination host2 <li><b>Enhancement</b>: Added --nomixfolders to avoid merging folders that are considered different on host1 but the same on destination host2
because of case sensitivities and insensitivities.</li> because of case sensitivities and insensitivities.</li>
<li><b>Bug fix</b>: Fixed "imapsync doesn't see created folders in the listing of folder sizes at the end". (second time this bug shows up)</li> <li><b>Bug fix</b>: Fixed "imapsync doesn't see created folders in the listing of folder sizes at the end". (second time this bug shows up)</li>
</ul> </ul>
<ul> <ul>
<li><b>1.592</b> Logging by default! (an internal feature now)</li> <li><b>1.592</b> (2014/05/22) Logging by default! (an internal feature now)</li>
<li><b>Caveat to upgrade</b>: New <b>IO::Tee</b> Perl module dependency, for logging. See the <a href="../INSTALL">INSTALL</a> file.</li> <li><b>Caveat to upgrade</b>: New <b>IO::Tee</b> Perl module dependency, for logging. See the <a href="../INSTALL">INSTALL</a> file.</li>
<li><b>Windows upgrade</b>: Win32 binary is now distributed in a zip file with two batches scripts ready to use it.</li> <li><b>Windows upgrade</b>: Win32 binary is now distributed in a zip file with two batches scripts ready to use it.</li>
@ -404,7 +450,7 @@ because of case sensitivities and insensitivities.</li>
</ul> </ul>
<ul> <ul>
<li><b>1.584</b></li> <li><b>1.584</b> (2014/02/05)</li>
<li><b>Enhancement</b>: Added --minmaxlinelength to select messages with long lines only. <li><b>Enhancement</b>: Added --minmaxlinelength to select messages with long lines only.
It helps to diagnostic Echange error on messages with lines longer than 9000 characters</li> It helps to diagnostic Echange error on messages with lines longer than 9000 characters</li>
<li><b>Enhancement</b>: Added --debugmaxlinelength</li> <li><b>Enhancement</b>: Added --debugmaxlinelength</li>
@ -555,7 +601,7 @@ by ignoring PERMANENTFLAGS (Exchange tests)</li>
<!--#config timefmt="%D" --> <!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" --> <!--#config timefmt="%A %B %d, %Y" -->
<b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b> <b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: news.shtml,v 1.50 2017/09/11 03:04:46 gilles Exp gilles $)<br /> ($Id: news.shtml,v 1.54 2018/05/06 15:03:59 gilles Exp gilles $)<br />
<a href="#TOP">Top of the page</a> <a href="#TOP">Top of the page</a>
</p> </p>
</body></html> </body></html>

77
S/no_download.shtml Normal file
View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>No imapsync download here</title>
<meta name="generator" content="Bluefish 1.0.7"/>
<meta name="author" content="Gilles LAMIRAL"/>
<meta name="date" content="2014-12-04T09:04:24+0100"/>
<meta name="copyright" content=""/>
<meta name="keywords" content=""/>
<meta name="description" content=""/>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8"/>
<meta http-equiv="content-style-type" content="text/css"/>
<meta http-equiv="expires" content="0"/>
<link href="../S/style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<h1>No imapsync download here</h1>
<p>
Imapsync is <b>no longer gratis</b> from this webpage.<br/>
You can <a href="../#buy_all"><b>purchase imapsync</b></a>.<br/>
</p>
<!--
<p>
Imapsync is still free software with the most open license of the universe:
<a href="../NOLIMIT">NOLIMIT</a>, <b>no limit to do anything with this work and this license</b>.
</p>
<p>For zealot developpers devoted to liberty and fine fair fare sharing,
free in free software means more free as in "free speech"
than free as in "free beer", at least as long as they never have
to pay for free speech software.
</p>
<p>Imapsync was free, open and gratis; now it is free, open and
not gratis from the homepage. It is the best decision I've done
about imapsync to continue to maintain it.
See detailed motivations in this
<a href="http://www.linux-france.org/prj/imapsync_list/msg00459.html">call for business solution</a>.
</p>
<p>"Download and donate if happy" doesn't work well.<br/>
"Pay for download and I pay back if unhappy" works well.
</p>
<p>Anyway, if you're poor or stingy but smart enough to type imapsync in a search engine
and click on the second link then you should get access to a free beer imapsync on github.
</p>
-->
<p>Gilles Lamiral.</p>
<hr/>
<p>
<a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
<a href="http://jigsaw.w3.org/css-validator/check/referer">
<img style="border:0;width:88px;height:31px"
src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
alt="CSS Valide !" /></a>
<br/>
<!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" -->
<b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b><br/>
($Id: no_download.shtml,v 1.14 2017/11/06 00:22:20 gilles Exp gilles $)
</p>
</body>
</html>

View File

@ -48,32 +48,30 @@ You may log into your account at <a href="http://www.paypal.com/">www.paypal.com
to view details of this transaction (if you have a Paypal account). to view details of this transaction (if you have a Paypal account).
</p> </p>
<p>You will find the latest <b>imapsync.exe binary</b> release <!--#exec cmd="cat ../VERSION_EXE" --><br/> <p>You will find <b>imapsync</b> release <!--#exec cmd="cat ../VERSION" --> at this
and the latest <b>imapsync source code</b> release <!--#exec cmd="cat ../VERSION" --> at this <a href="../dist2/"><b>download page</b></a>.
<a href="../dist/"><b>download page</b></a>.
</p> </p>
<p>Old imapsync releases are in the <a href="../dist/old_releases/">dist/old_releases/</a> directory.</p>
<p> <p>
Next steps are the imapsync <a href="../#install" >installation</a> Next step is imapsync <a href="../#install" >installation</a>
and then your first runs following the <a href="../#doc" >tutorial</a>. and then your first runs following the <a href="../#doc" >tutorial</a>.
</p> </p>
<p>You will receive an invoice soon, in a couple of weeks at the worst. <p>You will receive an invoice soon, in a couple of weeks at the worst.
Ask for it if you need it before.</p> Ask for it if you need it before.</p>
<p>Next imapsync releases will be available for lifetime without extra payment.<br/> <p>Next imapsync releases will be available to you for lifetime without extra payment.<br/>
This current page will be updated to reflect the lastest release of imapsync.<br/> This current page will be updated to reflect the lastest release of imapsync.<br/>
You will be soon subscribed to the newsletter announcing new releases (and only new releases).</p> You will be soon subscribed to the newsletter announcing new imapsync releases and services (and only that).</p>
<p>For <b>professionnal support</b>, in order to explain your <b>specific needs</b>, <p>For <b>professional support</b>, in order to explain your <b>specific needs</b>,
find <b>best solutions</b> for them, <b>avoid loosing time</b>, find <b>best solutions</b> for them, <b>avoid loosing time</b>,
and <b>succeed</b> your migration in the best conditions, <b>contact me</b> and <b>succeed</b> your migration in the best conditions, <b>contact me</b>
(Gilles LAMIRAL) by email or phone at:</p> (Gilles LAMIRAL) by email or phone at:</p>
<ul> <ul>
<li>Email address: <b>gilles.lamiral@laposte.net</b>.</li> <li>Email address: <b>gilles@lamiral.info</b>.</li>
<li>Professionnal phone number: <b>+33 9 51 84 42 42</b> (in France) I can <b>call you back</b> toll-free in many countries.</li> <li>Professionnal phone number: <b>+33 9 51 84 42 42</b> (in France) I can <b>call you back</b> toll-free in many countries.</li>
<li>Mobile phone number: <b>+33 6 19 22 03 54</b> (in France).</li> <li>Mobile phone number: <b>+33 6 19 22 03 54</b> (in France).</li>
</ul> </ul>
@ -87,7 +85,7 @@ and <b>succeed</b> your migration in the best conditions, <b>contact me</b>
</p> </p>
<p><b>Gilles LAMIRAL</b><br/> <p><b>Gilles LAMIRAL</b><br/>
gilles.lamiral@laposte.net</p> gilles@lamiral.info</p>
<hr /> <hr />
<p> <p>
@ -120,7 +118,7 @@ style="border:0;width:88px;height:31px"
<!--#config timefmt="%D" --> <!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" --> <!--#config timefmt="%A %B %d, %Y" -->
<b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b> <b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: paypal_return.shtml,v 1.32 2016/12/20 10:06:54 gilles Exp gilles $) ($Id: paypal_return.shtml,v 1.35 2018/04/10 00:26:50 gilles Exp gilles $)
</p> </p>
<!-- Google Code for Achat imapsync Conversion Page --> <!-- Google Code for Achat imapsync Conversion Page -->
<script type="text/javascript"> <script type="text/javascript">

View File

@ -1,3 +1,4 @@
User-agent: * User-agent: *
Disallow: Disallow: /dist/
#Disallow: /X/

View File

@ -1,5 +1,5 @@
/* $Id: style.css,v 1.12 2016/12/20 10:00:46 gilles Exp gilles $ */ /* $Id: style.css,v 1.13 2018/01/29 02:07:02 gilles Exp gilles $ */
/* http://www.w3schools.com/html/html5_browsers.asp */ /* http://www.w3schools.com/html/html5_browsers.asp */
@ -47,10 +47,10 @@ body {
@media screen and ( min-width: 960px ) { @media screen and ( min-width: 960px ) {
div.list { div.list {
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
} }
} }
div.poll { div.poll {

0
S/template_html5.shtml Executable file → Normal file
View File

0
S/template_xhtml1.shtml Executable file → Normal file
View File

120
S/testimonial.shtml Normal file
View File

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html lang="en" id="TOP">
<head>
<meta charset="utf-8" >
<title>Testimonials for Imapsync</title>
<meta name="author" content="Gilles LAMIRAL" >
<meta name="copyright" content="None">
<link rel="icon" type="image/png" href="../S/images/logo_imapsync_s.png" >
<link href="../S/style.css" rel="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!--
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
-->
<!--
The link to the HTML5Shiv must be placed in the <head> element, after any stylesheets
http://www.w3schools.com/html/html5_browsers.asp
-->
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<section>
<h1>Very good tweets about Imapsync <a id="title1" href="../#TOP"><small>(back to menu)</small></a>
</h1>
<p>
I'm not sure I deserve such great quotes for my work on Imapsync, anyway here they are and I'm very glad of them!<br/>
</p>
<!--#include file="S/tw-mention.html" -->
<blockquote class="twitter-tweet" data-cards="hidden" data-lang="en">
<p lang="en" dir="ltr">For me, this is still the most useful tool anyone has ever created: <a href="https://t.co/DxQDXkQwHk">https://t.co/DxQDXkQwHk</a></p>
&mdash; Peter Schmalfeldt (@mrmidi) <a href="https://twitter.com/mrmidi/status/578037186156703745">March 18, 2015</a>
</blockquote>
<hr>
<blockquote class="twitter-tweet" data-lang="en">
<p lang="en" dir="ltr">Right next to chocolate, imapsync is humankinds best invention.</p>
&mdash; Mathias Maul (@dontcallmedarth)
<a href="https://twitter.com/dontcallmedarth/status/587969510583459840">April 14, 2015</a>
</blockquote>
<hr>
<blockquote class="twitter-tweet" data-lang="en">
<p lang="en" dir="ltr">Imapsync was the best investment I've ever done.</p> &mdash; Uwe Keim
<a href="https://serverfault.com/questions/818818/imapsync-or-php-to-migrate-email">Dec 6 '16 at 12:17</a>
</blockquote>
<hr>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">My life right now. Would be 10x worse without <a href="https://twitter.com/imapsync">@imapsync</a>
</p>&mdash; G.C. (@its_gc)
<a href="https://twitter.com/its_gc/status/591711647850434561">April 24, 2015</a></blockquote>
<hr>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">A week of heavy use of <a href="https://twitter.com/imapsync">@imapsync</a> and I&#39;ve shifted over 17000 mailboxes from an <a href="https://twitter.com/gsuite">@gsuite</a> domain over to <a href="https://twitter.com/Office365">@Office365</a> at work. Cheers, Gilles!</p>&mdash; Graeme Fowler (@graemefowler) <a href="https://twitter.com/graemefowler/status/908807906576994304">September 15, 2017</a></blockquote>
<hr>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">After about a week of looking for an email transfer tool and pulling out my hair, <a href="https://twitter.com/imapsync">@imapsync</a> was a life-saver.</p>&mdash; My Web Maestro (@MyWebMaestro) <a href="https://twitter.com/MyWebMaestro/status/650427662964510720">October 3, 2015</a></blockquote>
<hr>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Yeahhh Boy!!! Imapsync works like a charm... 500 account/100 Gb/master imap user/ssl/ one mini bash do that and going for more</p>&mdash; RadicaLibre (@RadicaLibreVE) <a href="https://twitter.com/RadicaLibreVE/status/624109591505313792">July 23, 2015</a></blockquote>
<hr>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Hi Gilles! If every tool just fracking worked like this, my life would be sooo much easier. Thanks a ton for this simple to use yet extremely powerfull tool! I&#39;m glad you made it easy to (get) support as well ;)</p>&mdash; Jeroen (@Planet_Jeroen) <a href="https://twitter.com/Planet_Jeroen/status/946080311661776896?ref_src=twsrc%5Etfw">December 27, 2017</a></blockquote>
<hr>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</section>
<footer>
<a href="http://validator.w3.org/check?uri=referer">
<img
src="../S/images/valid-W3C-html5.png"
alt="Valid HTML5" height="31" width="88" >
</a>
<a href="http://jigsaw.w3.org/css-validator/check/referer">
<img style="border:0;width:88px;height:31px"
src="../S/images/vcss-blue"
alt="CSS Valide !" >
</a>
<a href="http://www.anybrowser.org/campaign/">
<img style="border:0;width:88px;height:31px"
src="../S/images/ab_jlh.png"
alt="Viewable With Any Browser" >
</a>
<hr>
<p>
<!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" -->
<b>This document was last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: testimonial.shtml,v 1.4 2018/02/12 21:55:37 gilles Exp gilles $)<br>
<a href="#TOP">Top of the page</a>
</p>
</footer>
</body>
</html>

97
S/trial.shtml Normal file
View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en" id="TOP">
<head>
<meta charset="utf-8" >
<title>Imapsync trial</title>
<meta name="author" content="Gilles LAMIRAL" >
<meta name="copyright" content="None">
<link rel="icon" type="image/png" href="../S/images/logo_imapsync_s.png" >
<link href="../S/style.css" rel="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!--
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
-->
<!--
The link to the HTML5Shiv must be placed in the <head> element, after any stylesheets
http://www.w3schools.com/html/html5_browsers.asp
-->
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<section>
<h1>Imapsync trial <a id="title1" href="../#TOP"><small>(back to menu)</small></a>
</h1>
<p><b>I thank you for trying Imapsync!</b></p>
<p>You will find <b>imapsync</b> release <!--#exec cmd="cat ../VERSION" --> at this
<a href="../dist/"><b>download page</b></a>.
</p>
<p>
Next step is imapsync <a href="../#install" >installation</a>
and then your first runs following the <a href="../#doc" >tutorial</a>.
</p>
<p>
<b>I wish you successful imap transfers!</b><br/>
<a href="../#buy_all">Purchase imapsync</a>, lifetime upgrades!
</p>
<p><b>Gilles LAMIRAL</b><br/>
gilles@lamiral.info
</p>
</section>
<footer>
<hr>
<a href="http://validator.w3.org/check?uri=referer">
<img
src="../S/images/valid-W3C-html5.png"
alt="Valid HTML5" height="31" width="88" >
</a>
<a href="http://jigsaw.w3.org/css-validator/check/referer">
<img style="border:0;width:88px;height:31px"
src="../S/images/vcss-blue"
alt="CSS Valide !" >
</a>
<a href="http://www.anybrowser.org/campaign/">
<img style="border:0;width:88px;height:31px"
src="../S/images/ab_jlh.png"
alt="Viewable With Any Browser" >
</a>
<hr>
<p>
<!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" -->
<b>This document was last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: trial.shtml,v 1.4 2018/04/10 00:26:50 gilles Exp gilles $)<br>
<a href="#TOP">Top of the page</a>
</p>
</footer>
</body>
</html>

View File

@ -1,7 +1,7 @@
<script type="text/javascript"> <script>
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs'); !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
</script> </script>

Some files were not shown because too many files have changed in this diff Show More