mirror of
https://github.com/imapsync/imapsync.git
synced 2024-11-17 00:02:29 +01:00
1.882
This commit is contained in:
parent
65f8552a91
commit
9a927be251
6
CREDITS
6
CREDITS
@ -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
228
ChangeLog
@ -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.
|
||||||
----------------------------
|
----------------------------
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
=======================================================================
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
@ -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?
|
||||||
|
|
||||||
|
@ -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?
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
@ -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".
|
||||||
|
|
||||||
|
@ -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 \
|
||||||
|
@ -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
|
||||||
|
24
FAQ.d/FAQ.Folders_Sizes.txt
Normal file
24
FAQ.d/FAQ.Folders_Sizes.txt
Normal 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
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
=======================================================================
|
@ -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
|
||||||
|
@ -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?
|
||||||
|
@ -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,
|
||||||
|
@ -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?
|
||||||
|
|
||||||
|
49
FAQ.d/FAQ.Migration_Plan.txt
Normal file
49
FAQ.d/FAQ.Migration_Plan.txt
Normal 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
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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
60
FAQ.d/FAQ.POP3.txt
Normal 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/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
=======================================================================
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
=======================================================================
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
=======================================================================
|
=======================================================================
|
@ -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
|
||||||
|
|
||||||
|
|
@ -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.
|
||||||
|
@ -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
4
FAQ.d/memo
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
( cd .. && make upload_FAQ )
|
||||||
|
|
@ -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 ==
|
||||||
|
@ -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
|
||||||
|
@ -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 ==
|
||||||
==============
|
==============
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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/
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 \
|
||||||
|
@ -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 =
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
======================
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
40
LOG_imapsync/imapsync_abortme.log
Normal file
40
LOG_imapsync/imapsync_abortme.log
Normal 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
227
Makefile
@ -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
181
README
@ -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.
|
||||||
|
|
||||||
|
@ -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
18
S/bc-payment.html
Executable file → Normal 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
1
S/button.js
Normal 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
30
S/external.shtml
Executable file → Normal 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
34
S/guestbook.shtml
Executable file → Normal 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>
|
||||||
|
BIN
S/images/bitcoin_buy_now_large.png
Normal file
BIN
S/images/bitcoin_buy_now_large.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
BIN
S/images/logo_imapsync_486x486.png
Normal file
BIN
S/images/logo_imapsync_486x486.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
Binary file not shown.
@ -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
@ -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 |
@ -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";
|
|
||||||
|
|
||||||
}
|
|
@ -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
@ -1,5 +0,0 @@
|
|||||||
LOGFILE: imapcopy.log
|
|
||||||
IMAPCOPY: imapcopy.pl
|
|
||||||
PROCESS_LIMIT: 8
|
|
||||||
DEBUG: 0
|
|
||||||
SHOWIMAP: 0
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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
@ -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>
|
|
@ -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
@ -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
@ -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
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
@ -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
23
S/imapservers.shtml
Executable file → Normal 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>
|
||||||
|
|
||||||
|
@ -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
76
S/news.shtml
Executable file → Normal 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
77
S/no_download.shtml
Normal 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>
|
@ -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">
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
User-agent: *
|
User-agent: *
|
||||||
Disallow:
|
Disallow: /dist/
|
||||||
|
#Disallow: /X/
|
||||||
|
|
||||||
|
10
S/style.css
10
S/style.css
@ -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
0
S/template_html5.shtml
Executable file → Normal file
0
S/template_xhtml1.shtml
Executable file → Normal file
0
S/template_xhtml1.shtml
Executable file → Normal file
120
S/testimonial.shtml
Normal file
120
S/testimonial.shtml
Normal 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>
|
||||||
|
— 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 humankind’s best invention.</p>
|
||||||
|
— 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> — 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>— 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'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>— 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>— 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>— 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'm glad you made it easy to (get) support as well ;)</p>— 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
97
S/trial.shtml
Normal 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>
|
||||||
|
|
@ -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
Loading…
Reference in New Issue
Block a user