21.11.2008

Перенос почты из одного аккаунта Gmail в другой

Нужно было перенести почту из одного ящика Gmail в другой. Один из них на самом деле в домене на Google Applications, но принципиально это дела не меняет. Метод переноса предельно прост: подключаемся к обоим аккаунтам по IMAP4 и из аккаунта-источника копируем все сообщения, лежащие в папке download в папку upload аккаунта-получателя.

На малых объёмах почты процедуру наверное можно произвести с помощью какого-нибудь почтового клиента. Но мне нужно было перенести несколько тысяч сообщений. Icedove не справился, а Sylhead Claws я решил не настраивать, поскольку быстрее и надёжнее - наскриптовать.


# -*- coding: utf-8 -*-

from progressbar import ProgressBar, SimpleProgress, Percentage, Bar, ETA
import email
import imaplib
import sys

SRC_HOST = 'imap.gmail.com'
SRC_USER = ''
SRC_PASS = ''
SRC_MAILBOX = 'download' 

DST_HOST = 'imap.gmail.com'
DST_USER = ''
DST_PASS = ''
DST_MAILBOX = 'upload'

class MigrationProgressBar(ProgressBar):
    def __init__(self, maxval):
        widgets = [SimpleProgress(), '  ', 
                   Percentage(), '  ', Bar(), '  ', ETA()]
        super(MigrationProgressBar, self).__init__(maxval, widgets)
    
    def _need_update(self):
        return True

def imap_open(host, username, password, mailbox, readonly=False):
    imap = imaplib.IMAP4_SSL(host)
    imap.login(username, password)
    imap.select(mailbox, readonly)
    return imap

def imap_close(imap):
    imap.close()
    imap.logout()
    del imap
    return

def main():
    src = imap_open(SRC_HOST, SRC_USER, SRC_PASS, SRC_MAILBOX, True)
    dst = imap_open(DST_HOST, DST_USER, DST_PASS, DST_MAILBOX, False)
    
    id_list = list(src.search(None, 'ALL')[1][0].split())
    progress = MigrationProgressBar(len(id_list)).start()
    
    for id in id_list:
        _, data = src.fetch(id, '(RFC822)')
        message_str = data[0][1]
        message = email.message_from_string(message_str)
        date_time = email.utils.parsedate(message['Date'])
        dst.append(DST_MAILBOX, '', date_time, message_str)
        progress.update(id_list.index(id))

    imap_close(src)
    imap_close(dst)
    
    return
    

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass
    sys.stdout.write('\n')
    exit()

#EOF

Скрипт требует библиотеки progressbar. Её пока ни в stable, ни в testing дистрах Debian нет. Можно либо поставить из unstable, либо через easy_install (

esay_install progressbar
), либо вообще её из кода выкинуть и заменить на обычный print.

На хосте с каналом в 100Мбит 8000 сообщений перекачались за полтора часа.

Комментарии

21.11.08 13:18 axet комментирует:

fetchmail не судьба?

21.11.08 13:23 Алексей комментирует:

Интересный способ, но можно было сделать проще. В аккаунте, откуда нужно перенести почту, открываем доступ по POP3 протоколу и выбираем Включить POP для всех писем (даже для тех, которые уже загружены). Во втором аккаунте добавляем первый аккаунт в разделе Получать почту из других аккаунтов. И все, остальное сделает гугл сам.

21.11.08 13:32 jetxee комментирует:

Положил в закладки. Спасибо.

21.11.08 13:39 Flycat комментирует:

Я из Яндекса в Google свою почту перенёс банально по POP3. Даже даты сообщений сохранились.

21.11.08 13:44 Anonymous комментирует:

http://uzhe.vtomske.ru/2008/11/10/rezervnaya-kopiya-gmail/

какбы уже есть…

21.11.08 13:51 Pavel Vyazovoi комментирует:

Готовое решение: offlineimap.
Синхронизирует два imap-аккаунта.

21.11.08 13:53 uptimebox комментирует:

Вот не знаю как насчёт второго предложения, а fetchmail - не судьба.

Fetchmail умеет доставлять только в мейлбокс, либо по smtp. А Gmail, получая сообщение по smtp показывает датой письма в списках время последней доставки. Т.е. то время, когда Gmail его получил. Не очень удобно.

21.11.08 14:14 uptimebox комментирует:

В общем понятно. Велосипед изобрёл. Ну не выкидывать же, да? Жалко =)