Pull to refresh

IMAPSync. Перенос почты между серверами

Reading time13 min
Views77K
В этой статье я хочу поделиться опытом переноса почты между разными серверами с помощью замечательной утилиты IMAPSync.

— Получение IMAPSync.exe из исходников github (компиляция под Windows).
— Перенос почты по IMAP между серверами.

В моем случае встала задача перенести почту со своего сервера IDECO на сервера pdd.yandex.ru. Средствами Яндекса сделать это мне не удалось, инструмент по импорту для домена и инструмент по сбору почты в свойствах ящика выдавал всегда одну ошибку — неверный пароль. Техническая поддержка отвечала раз в сутки, а проблема не решалась. Были рекомендации сменить пароль, подождать, отключить двухфакторную авторизацию и т.п. В общем стандартные отписки, к сожалению. Использовать biz.mail.ru, который прекрасно все импортировал на тестовых ящиках, не хотелось. Так как имею больше опыта с Яндексом, и больше нравится работа почты от Яндекса, было принято решение найти другой способ переноса почты. Им и стал IMAPSync.

Начинаем, при условии, что на сервере назначения у нас созданы пустые (или не очень) ящики с нужными нам логинами и паролями.

Компиляция IMAPSync.exe из исходников под Windows


  1. Подготавливаем инструменты для компиляции:
    Для примера будем использовать путь «D:\IMAPSync\»

    Скачиваем последнюю версию IMAPSync с github, на примере версии IMAPSync v1.678
    Распаковываем архив в D:\IMAPSync\imapsync-1.678\*.*
    Копируем файл imapsync из D:\IMAPSync\imapsync-1.678\ в D:\IMAPSync\imapsync-1.678\W\

    Скачиваем Strawberry-perl, на примере версии Strawberry-perl-5.22.2.1-32bit-portable.zip
    Подробнее про разные версии и проблемы
    Успешная установка пакетов и компиляция IMAPSync проверена на версиях:
    strawberry-perl-5.20.3.3-32bit-portable
    strawberry-perl-5.22.1.3-32bit-portable
    strawberry-perl-5.22.2.1-32bit-portable
    

    Ошибки обнаружены на версиях:
    strawberry-perl-5.24.0.1-32bit-portable (не отрабатывает ppm install Unicode::String)
    
    Распаковываем архив в D:\IMAPSync\strawberry-perl-5.22.2.1-32bit-portable\*.*
    Запускаем D:\IMAPSync\strawberry-perl-5.22.2.1-32bit-portable\portableshell.bat

    Появится командная строка (переменные среды perl тут уже настроены), в ней выполняем
    ppm install Unicode::String 
    D:\IMAPSync\imapsync-1.678\W\install_modules.bat 
    

    На этом этапе брандмауэр (firewall) может запросить открыть доступ для приложения «D:\IMAPSync\strawberry-perl-5.22.2.1-32bit-portable\perl\bin\perl.exe»
    Необходимо разрешить сетевой доступ для успешной установки модулей.

    Выполняем повторно команду для наглядного мониторинга ошибок
    D:\IMAPSync\imapsync-1.678\W\install_modules.bat
    

    Убеждаемся, что все модули установлены, ошибок нет, можно переходить к компиляции.

  2. Запускаем компиляцию:
    D:\IMAPSync\imapsync-1.678\W\build_exe.bat
    

    На выходе получаем imapsync.exe — запускаем его в том же окне командной строки и проверяем, должен показать справку:
    Результат. Справка по всем параметрам
     Several options are mandatory.
     str means string
     int means integer
     reg means regular expression
     cmd means command
    
     --dry               : Makes imapsync doing nothing, just print what would
                           be done without --dry.
    
     --host1        str  : Source or "from" imap server. Mandatory.
     --port1        int  : Port to connect on host1. Default is 143, 993 if --ssl1
     --user1        str  : User to login on host1. Mandatory.
     --showpasswords     : Shows passwords on output instead of "MASKED".
                           Useful to restart a complete run by just reading the log.
     --password1    str  : Password for the user1.
     --host2        str  : "destination" imap server. Mandatory.
     --port2        int  : Port to connect on host2. Default is 143, 993 if --ssl2
     --user2        str  : User to login on host2. Mandatory.
     --password2    str  : Password for the user2.
    
     --passfile1    str  : Password file for the user1. It must contain the
                           password on the first line. This option avoids to show
                           the password on the command line like --password1 does.
     --passfile2    str  : Password file for the user2. Contains the password.
    
     --ssl1              : Use a SSL connection on host1.
     --ssl2              : Use a SSL connection on host2.
     --tls1              : Use a TLS connection on host1.
     --tls2              : Use a TLS connection on host2.
     --debugssl     int  : SSL debug mode from 0 to 4.
    
     --timeout1     int  : Connection timeout in seconds for host1.
                           Default is 120 and 0 means no timeout at all.
     --timeout2     int  : Connection timeout in seconds for host2.
                           Default is 120 and 0 means no timeout at all.
    
     --authmech1    str  : Auth mechanism to use with host1:
                           PLAIN, LOGIN, CRAM-MD5 etc. Use UPPERCASE.
     --authmech2    str  : Auth mechanism to use with host2. See --authmech1
    
     --authuser1    str  : User to auth with on host1 (admin user).
                           Avoid using --authmech1 SOMETHING with --authuser1.
     --authuser2    str  : User to auth with on host2 (admin user).
     --proxyauth1        : Use proxyauth on host1. Requires --authuser1.
                           Required by Sun/iPlanet/Netscape IMAP servers to
                           be able to use an administrative user.
     --proxyauth2        : Use proxyauth on host2. Requires --authuser2.
    
     --authmd51          : Use MD5 authentification for host1.
     --authmd52          : Use MD5 authentification for host2.
     --domain1      str  : Domain on host1 (NTLM authentication).
     --domain2      str  : Domain on host2 (NTLM authentication).
    
    
     --folder       str  : Sync this folder.
     --folder       str  : and this one, etc.
     --folderrec    str  : Sync this folder recursively.
     --folderrec    str  : and this one, etc.
    
     --folderfirst  str  : Sync this folder first. --folderfirst "Work"
     --folderfirst  str  : then this one, etc.
     --folderlast   str  : Sync this folder last. --folderlast "[Gmail]/All Mail"
     --folderlast   str  : then this one, etc.
    
     --nomixfolders      : Do not merge folders when host1 is case sensitive
                           while host2 is not (like Exchange). Only the first
                           similar folder is synced (ex: Sent SENT sent -> Sent).
    
     --skipemptyfolders  : Empty host1 folders are not created on host2.
    
     --include      reg  : Sync folders matching this regular expression
     --include      reg  : or this one, etc.
                           in case both --include --exclude options are
                           use, include is done before.
     --exclude      reg  : Skips folders matching this regular expression
                           Several folders to avoid:
                            --exclude 'fold1|fold2|f3' skips fold1, fold2 and f3.
     --exclude      reg  : or this one, etc.
    
     --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.
    
     --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.
     --regextrans2  reg  : Apply the whole regex to each destination folders.
     --regextrans2  reg  : and this one. etc.
                           When you play with the --regextrans2 option, first
                           add also the safe options --dry --justfolders
                           Then, when happy, remove --dry, remove --justfolders.
                           Have in mind that --regextrans2 is applied after prefix
                           and separator inversion. For examples see
                           http://imapsync.lamiral.info/FAQ.d/FAQ.Folders_Mapping.txt
    
     --tmpdir       str  : Where to store temporary files and subdirectories.
                           Will be created if it doesn't exist.
                           Default is system specific, Unix is /tmp but
                           it's often small and deleted at reboot.
                           --tmpdir /var/tmp should be better.
     --pidfile      str  : The file where imapsync pid is written.
     --pidfilelocking    : Abort if pidfile already exists. Usefull to avoid
                           concurrent transfers on the same mailbox.
    
     --nolog             : Turn off logging on file
     --logfile      str  : Change the default log filename (can be dirname/filename).
     --logdir       str  : Change the default log directory. Default is LOG_imapsync
    
     --prefix1      str  : Remove prefix to all destination folders
                           (usually INBOX. or INBOX/ or an empty string "")
                           you have to use --prefix1 if host1 imap server
                           does not have NAMESPACE capability, so imapsync
                           suggests to use it. All other cases are bad.
     --prefix2      str  : Add prefix to all host2 folders. See --prefix1
     --sep1         str  : Host1 separator in case NAMESPACE is not supported.
     --sep2         str  : Host2 separator in case NAMESPACE is not supported.
    
     --skipmess     reg  : Skips messages maching the regex.
                           Example: 'm/[\x80-ff]/' # to avoid 8bits messages.
                           --skipmess is applied before --regexmess
     --skipmess     reg  : or this one, etc.
    
     --pipemess     cmd  : Apply this cmd command to each message content
                           before the copy.
     --pipemess     cmd  : and this one, etc.
     
     --disarmreadreceipts : Disarms read receipts (host2 Exchange issue)
    
     --regexmess    reg  : Apply the whole regex to each message before transfer.
                           Example: 's/\000/ /g' # to replace null by space.
     --regexmess    reg  : and this one, etc.
    
     --regexflag    reg  : Apply the whole regex to each flags list.
                           Example: 's/"Junk"//g' # to remove "Junk" flag.
     --regexflag    reg  : and this one, etc.
    
     --delete            : Deletes messages on host1 server after a successful
                           transfer. Option --delete has the following behavior:
                           it marks messages as deleted with the IMAP flag
                           \Deleted, then messages are really deleted with an
                           EXPUNGE IMAP command.
    
     --delete2           : Delete messages in host2 that are not in
                           host1 server. Useful for backup or pre-sync.
     --delete2duplicates : Delete messages in host2 that are duplicates.
                           Works only without --useuid since duplicates are
                           detected with an header part of each message.
    
     --delete2folders    : Delete folders in host2 that are not in host1 server.
                           For safety, first try it like this (it is safe):
                           --delete2folders --dry --justfolders --nofoldersizes
     --delete2foldersonly   reg : Deleted only folders matching regex.
                                  Example: --delete2foldersonly "/^Junk$|^INBOX.Junk$/"
     --delete2foldersbutnot reg : Do not delete folders matching regex.
                                  Example: --delete2foldersbutnot "/Tasks$|Contacts$|Foo$/"
     --noexpunge         : Do not expunge messages on host1.
                           Expunge really deletes messages marked deleted.
                           Expunge is made at the beginning, on host1 only.
                           Newly transferred messages are also expunged if
                           option --delete is given.
                           No expunge is done on host2 account (unless --expunge2)
     --expunge1          : Expunge messages on host1 after messages transfer.
     --expunge2          : Expunge messages on host2 after messages transfer.
     --uidexpunge2       : uidexpunge messages on the host2 account
                           that are not on the host1 account, requires --delete2
     --nomixfolders      : Avoid merging folders that are considered different on
                           host1 but the same on destination host2 because of
                           case sensitivities and insensitivities.
    
     --syncinternaldates : Sets the internal dates on host2 same as host1.
                           Turned on by default. Internal date is the date
                           a message arrived on a host (mtime).
     --idatefromheader   : Sets the internal dates on host2 same as the
                           "Date:" headers.
    
     --maxsize      int  : Skip messages larger  (or equal) than  int  bytes
     --minsize      int  : Skip messages smaller (or equal) than  int  bytes
     --maxage       int  : Skip messages older than  int  days.
                           final stats (skipped) don't count older messages
                           see also --minage
     --minage       int  : Skip messages newer than  int  days.
                           final stats (skipped) don't count newer messages
                           You can do (+ are the messages selected):
                           past|----maxage+++++++++++++++>now
                           past|+++++++++++++++minage---->now
                           past|----maxage+++++minage---->now (intersection)
                           past|++++minage-----maxage++++>now (union)
    
     --search       str  : Selects only messages returned by this IMAP SEARCH
                           command. Applied on both sides.
     --search1      str  : Same as --search for selecting host1 messages only.
     --search2      str  : Same as --search for selecting host2 messages only.
                           --search CRIT equals --search1 CRIT --search2 CRIT
    
     --exitwhenover int  : Stop syncing when total bytes transferred reached.
                           Gmail per day allows
                           2500000000 = 2.5 GB downloaded from Gmail as host2
                            500000000 = 500 MB uploaded to Gmail as host1.
    
     --maxlinelength int : skip messages with a line length longer than  int  bytes.
                           RFC 2822 says it must be no more than 1000 bytes.
    
     --useheader    str  : Use this header to compare messages on both sides.
                           Ex: Message-ID or Subject or Date.
     --useheader    str    and this one, etc.
    
     --subscribed        : Transfers subscribed folders.
     --subscribe         : Subscribe to the folders transferred on the
                           host2 that are subscribed on host1. On by default.
     --subscribeall      : Subscribe to the folders transferred on the
                           host2 even if they are not subscribed on host1.
    
     --nofoldersizes     : Do not calculate the size of each folder in bytes
                           and message counts. Default is to calculate them.
     --nofoldersizesatend: Do not calculate the size of each folder in bytes
                           and message counts at the end. Default is on.
     --justfoldersizes   : Exit after having printed the folder sizes.
    
     --syncacls          : Synchronises acls (Access Control Lists).
     --nosyncacls        : Does not synchronize acls. This is the default.
                           Acls in IMAP are not standardized, be careful.
    
     --usecache          : Use cache to speedup.
     --nousecache        : Do not use cache. Caveat: --useuid --nousecache creates
                           duplicates on multiple runs.
     --useuid            : Use uid instead of header as a criterium to recognize
                           messages. Option --usecache is then implied unless
                           --nousecache is used.
    
     --debug             : Debug mode.
     --debugfolders      : Debug mode for the folders part only.
     --debugcontent      : Debug content of the messages transfered. Huge ouput.
     --debugflags        : Debug mode for flags.
     --debugimap1        : IMAP debug mode for host1. Very verbose.
     --debugimap2        : IMAP debug mode for host2. Very verbose.
     --debugimap         : IMAP debug mode for host1 and host2.
     --debugmemory       : Debug mode showing memory consumption after each copy.
    
     --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.
     --testslive         : Run a live test with test1.lamiral.info imap server.
                           Useful to check the basics. Needs internet connexion.
    
     --version           : Print only software version.
     --noreleasecheck    : Do not check for new imapsync release (a http request).
     --releasecheck      : Check for new imapsync release (a http request).
     --noid              : Do not send/receive ID command to imap servers.
     --justconnect       : Just connect to both servers and print useful
                           information. Need only --host1 and --host2 options.
     --justlogin         : Just login to both host1 and host2 with users
                           credentials, then exit.
     --justfolders       : Do only things about folders (ignore messages).
    
     --help              : print this help.
    
     Example: to synchronize imap account "test1" on "test1.lamiral.info"
                         to  imap account "test2" on "test2.lamiral.info"
                         with test1 password "secret1"
                         and  test2 password "secret2"
    
     D:\IMAPSync\imapsync-imapsync-1.678\W\imapsync.exe ^
        --host1 test1.lamiral.info --user1 test1 --password1 secret1 ^
        --host2 test2.lamiral.info --user2 test2 --password2 secret2
    
    Here is a [MSWin32] system (Windows NT Fronik 6.2 Build 9200 x86)
    With perl 5.22.2 Mail::IMAPClient  3.38
    $Id: imapsync,v 1.678 2016/01/21 19:47:02 gilles Exp gilles $ 
    New imapsync release 1.684 available
    
    Homepage: http://imapsync.lamiral.info/

    Если все так, никаких ошибок нет, значит приложение готово, можно использовать.

Перенос почты по IMAP между серверами


  1. Копируем наше приложение \W\imapsync.exe в \examples\imapsync.exe. В папке \examples нас интересует несколько файлов:
    • imapsync_example.bat — тестирование настроек переноса и сам перенос почты для одного ящика
    • sync_loop_windows.bat и file.txt — перенос почты для массива ящиков

  2. Подготовка, тестирование, перенос одного ящика:
    Открываем файл imapsync_example.bat и прописываем наши реквизиты и параметры:
    .\imapsync.exe	^
       --host1 mx.example.ru  --user1 user@example.ru  --password1 "Pass123"  ^
       --host2 imap.yandex.ru  --user2 user@example.biz  --password2 "Pass123"  ^
       --ssl1  --ssl2  --sslargs1 SSL_verify_mode=0 --sslargs2 SSL_verify_mode=1 --skipheader "^(?!Message-Id)"  --automap  ^
       --regextrans2 "s/^INBOX\.(.+)/$1/"  --justfolders  --dry
    @PAUSE
    
    Небольшое описание параметров
    Сервер источника, логин ящика, пароль ящика:
    --host1 mx.example.ru --user1 user --password1 "Pass123"

    Сервер назначения, логин ящика, пароль ящика:
    --host2 imap.yandex.ru --user2 user@example.biz --password2 "Pass123"

    Использование SSL для сервера источника и назначения:
    --ssl1 --ssl2

    Если включено использование SSL (--ssl1 --ssl2), то лучше сразу настроить режим проверки сертификата.
    Принимать любой сертификат (=0), или проверять подлинность (=1).
    --sslargs1 SSL_verify_mode=0 --sslargs2 SSL_verify_mode=1

    Заметил, что если не указать эти настройки, то могут появлятся ошибки при переносе некоторых писем, или появление ошибки такого рода:
    Use of uninitialized value $sockargs[9] in join or string at Mail/IMAPClient.pm line 360.

    Игнорировать все заголовки в письме, кроме тех, что содержат «Message-Id». Этот параметр полезен в тех случаях, когда для одного письма на разных серверах генерируются разные заголовки, в моем случае они отличались. Яндекс для каждого письма добавлял одну дополнительную строчку, из-за чего письма дублировались при каждом последующем переносе почты. Если фильтровать заголовки по «Message-Id», то при каждом переносе почты, копируются только новые письма.
    --skipheader "^(?!Message-Id)"

    Автоматически определить и привязать папки на сервере источника к папкам на сервере назначения. Сама сравнивает названия и создает привязки, поддерживает папки с кириллицей в названиях. Inbox-> Входящие. Sent -> Отправленные…
    --automap

    Удаляет из названия INBOX во всех папках назначения. В моем случае IDECO все папки называет начиная с INBOX (INBOX.Sent, INBOX.Drafts и т.п.). Чтобы не создавать двойные названия в сервере назначения для папок, которые были созданы пользователем вручную. Тут стоит заметить, что это еще зависит от сервера.
    --regextrans2 "s/^INBOX\.(.+)/$1/"

    Выполнять операции только для папок. Письма не переносятся.
    --justfolders

    Эмуляция выполнения. Будет показан весь план работ, но физически ничего не переносится. Удобно для тестирования.
    --dry


    После прочтения описания запускаем и проверяем как произошла привязка наших папок. Если все успешно — здорово. Если нет, то можно воспользоваться параметрами ручной привязки. Например, параметры ниже создает привязку папок «INBOX.Junk» и «INBOX.Spam» к папке «Удаленные».
    --f1f2 "INBOX.Junk"="&BCMENAQwBDsENQQ9BD0ESwQ1-" --f1f2 "INBOX.Spam"="&BCMENAQwBDsENQQ9BD0ESwQ1-"
    

    Тут мы сталкиваемся с кодировкой. Чтобы определить как должны называться папки с кириллицей нужно заглянуть в логи (LOG_imapsync\*.txt), которые создаются после каждого выполнения программы.
    Folders mapping from --automap feature (use --f1f2 to override any mapping):
    [INBOX.Junk]                             -> [&BCEEPwQwBDw-] = [Спам]            
    [INBOX.Spam]                             -> [&BCEEPwQwBDw-] = [Спам]            
    [INBOX.Sent]                             -> [&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-] = [Отправленные]
    [INBOX.Drafts]                           -> [&BCcENQRABD0EPgQyBDgEOgQ4-] = [Черновики]
    [INBOX.Trash]                            -> [&BCMENAQwBDsENQQ9BD0ESwQ1-] = [Удаленные]
    

    Ну, а тут уже все ясно и понятно, и сама программа предлагает нам создать ручную привязку, если это необходимо.
    После прогона, убедившись, что все выглядит хорошо, удаляем параметр:
    --dry
    

    Запускаем, и проверяем как создались папки на нашем сервере назначения. Пока мы проверяем только папки. Если требуется, вносим правки в привязки. Если все выглядит так как нам нужно, отлично, переходим к письмам. Удаляем параметр:
    --justfolders
    

    Запускаем и проверяем как создаются папки и перемещаются письма на наш сервер назначения. Также вносим необходимые правки при необходимости. Если нам нужно было перенести только один ящик — то на этом мы закончили. Если нужно перенести больше, то переходим к следующему пункту.

  3. Перенос почты для нескольких ящиков.
    Открываем файл file.txt. Этот файл содержит хорошее описание и реальный пример, для демонстрации работы. С заполнением трудностей возникнуть не должно. Закомментируем в нем все примеры, и напишем свои данные ниже. Перечисляем все наши ящики которые хотим перенести.
    mx.example.ru;user;Pass123;imap.yandex.ru;user@example.biz;Pass123
    mx.example.ru;user2;Pass321;imap.yandex.ru;user2@example.biz;Pass321
    

    Открываем файл sync_loop_windows.bat на редактирование, и после строк:
    imapsync ^
      --host1 %%G --user1 %%H --password1 %%I ^
      --host2 %%J --user2 %%K --password2 %%L %arguments%
    

    Добавляем наши параметры, не забывая про символ "^" в конце строки после %arguments%, получаем в итоге:
    imapsync ^
      --host1 %%G --user1 %%H --password1 %%I ^
      --host2 %%J --user2 %%K --password2 %%L %arguments% ^
      --ssl1 --ssl2 --sslargs1 SSL_verify_mode=0 --sslargs2 SSL_verify_mode=1 --skipheader "^(?!Message-Id)"  --automap ^
      --regextrans2 "s/^INBOX\.(.+)/$1/" --justfolders --dry
    

    Сохраняем и запускаем. Проверяем как прошла отработка и удаляем параметры --justfolders --dry для запуска реального переноса всех папок и писем.
    Теперь остается только ждать завершения переноса почтовых ящиков и проверять логи. Для каждого ящика будет создан свой лог.

Дополнение


Несколько основных моментов которые я для себя выделил при изучении программы и отладке ошибок:
  • В папке \examples\FAQ.d есть отличный FAQ с примерами
  • При экспериментах с заголовками поможет параметр "--debug". В этом режиме показывается содержимое всех заголовков каждого письма.
  • В качестве сервера источника и назначения можно использовать один и тот же сервер, например, для удаления дубликатов.

Компиляция и работоспособность протестирована на Windows 10 64bit и Windows 7 64bit.

UPD 2016.07.10: Переписал раздел подготовки и компиляции используя портативную версию strawberry.
Уточнил версии, на которых установка пакетов и компиляция проходит без ошибок.
UPD 2016.07.11: Добавил команды проверки и игнорирования сертификатов SSL.
Tags:
Hubs:
Total votes 12: ↑9 and ↓3+6
Comments42

Articles