Скрипт для перемещения сообщений с одного сервера IMAP на другой - PullRequest
4 голосов
/ 11 августа 2011

Наш офис использует 2 сервера IMAP для электронной почты, один из них является сервером входящих сообщений и содержит последние сообщения электронной почты, а другой - сервером архивации.В основном мы используем Outlook 2010, и наш текущий процесс заключается в том, чтобы периодически перетаскивать отправленные сообщения с входящего сервера в архив.

Сегодня меня попросили заняться написанием скрипта, который периодически (вероятно, использует crontab) захватывал всеотправлять сообщения и перемещать их в архив.

Я рассмотрел пример SSL или telnet для доступа к серверу и поискам.Однако я не знаю, как лучше написать этот сценарий или как переместить файлы между серверами в среде IMAP.

Какой лучший способ сделать это?Я бы предпочел использовать Python просто с уровня комфорта, но если уже существует решение на другом языке, я мог бы с ним справиться.


Обновление:

Хорошо, вот код.В настоящее время он просто копирует сообщения, однако дублирует существующие сообщения на сервере архивации.

import imaplib
import sys

#copy from
f_server = 'some.secret.ip.address'
f_username = 'j@example.com'
f_password = 'password'
f_box_name = 'Sent Messages'

#copy to
t_server = 'archive.server.i.p'
t_username = 'username'
t_password = 'password'
t_box_name = 'test'

To = imaplib.IMAP4(t_server) 
To.login(t_username, t_password)
print 'Logged into mail server'

From = imaplib.IMAP4(f_server)
From.login(f_username, f_password)
print 'Logged into archive'

From.select(f_box_name)  #open box which will have its contents copied
print 'Fetching messages...'
typ, data = From.search(None, 'ALL')  #get all messages in the box
msgs = data[0].split()

sys.stdout.write(" ".join(['Copying', str(len(msgs)), 'messages']))

for num in msgs: #iterate over each messages id number
    typ, data = From.fetch(num, '(RFC822)')
    sys.stdout.write('.')
    To.append(t_box_name, None, None, data[0][1]) #add a copy of the message to the archive box specified above

sys.stdout.write('\n')

try:
    From.close()
From.logout()

try:
    To.close()
To.logout()

Некоторые источники:
Блог Дуга Хеллмана: imaplib - Клиентская библиотека IMAP4
Блог Тайлера Лесманна: Копирование почтовых ящиков IMAP с помощью Python и imaplib

Мне все еще нужно:

  • удалять / удалять сообщения на живом сервере
  • не копировать дубликаты (на самом деле это будет исправлено путем удаления оригиналов после копирования, но ...)
  • перехват ошибок

Обновление 2:

У кого-нибудь есть идеи, как не создавать дубликаты при копировании?(пока исключая возможность удаления оригиналов) Я подумал о поиске текста, но понял, что вложенные ответы могут скинуть это.

Ответы [ 3 ]

3 голосов
/ 26 февраля 2015

Вот что я в итоге использовал. Я не утверждаю, что он идеален, то, как он использует msg_num, а не id, немного рискованно. Но это довольно медленные движения, возможно, пару часов (на cron).

import imaplib

#copy from
from_server = {'server': '1.1.1.1',
               'username': 'j@example.com',
               'password': 'pass',
               'box_names': ['Sent', 'Sent Messages']}

#copy to
to_server = {'server': '2.2.2.2',
             'username': 'archive',
             'password': 'password',
             'box_name': 'Sent'}

def connect_server(server):
    conn = imaplib.IMAP4(server['server']) 
    conn.login(server['username'], server['password'])
    print 'Logged into mail server @ %s' % server['server']
    return conn

def disconnect_server(server_conn):
    out = server_conn.logout()

if __name__ == '__main__':
    From = connect_server(from_server)
    To = connect_server(to_server)

    for box in from_server['box_names']:
        box_select = From.select(box, readonly = False)  #open box which will have its contents copied
        print 'Fetching messages from \'%s\'...' % box
        resp, items = From.search(None, 'ALL')  #get all messages in the box
        msg_nums = items[0].split()
        print '%s messages to archive' % len(msg_nums)

        for msg_num in msg_nums:
            resp, data = From.fetch(msg_num, "(FLAGS INTERNALDATE BODY.PEEK[])") # get email
            message = data[0][1] 
            flags = imaplib.ParseFlags(data[0][0]) # get flags
            flag_str = " ".join(flags)
            date = imaplib.Time2Internaldate(imaplib.Internaldate2tuple(data[0][0])) #get date
            copy_result = To.append(to_server['box_name'], flag_str, date, message) # copy to archive

            if copy_result[0] == 'OK': 
                del_msg = From.store(msg_num, '+FLAGS', '\\Deleted') # mark for deletion

        ex = From.expunge() # delete marked
        print 'expunge status: %s' % ex[0]
        if not ex[1][0]: # result can be ['OK', [None]] if no messages need to be deleted
            print 'expunge count: 0'
        else:
            print 'expunge count: %s' % len(ex[1])

    disconnect_server(From)
    disconnect_server(To)
1 голос
/ 03 ноября 2011

Я не уверен, с каким объемом сообщений вы имеете дело, но вы можете извлечь Message-ID из каждого и использовать его, чтобы выяснить, является ли он дубликатом. Либо генерируйте список идентификаторов, уже находящихся на целевом сервере, каждый раз, когда вы готовитесь к перемещению сообщений, либо добавляйте их в простую базу данных по мере их архивирования.

Вы можете сузить область поиска с помощью дополнительного свойства сообщения, например Date, если поиск слишком дорогой, а затем удалить старые списки, когда они вам больше не нужны.

0 голосов
/ 21 августа 2015

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

Это похоже на общее требование. Вы, вероятно, не должны ничего настраивать на заказ.

Возможно, вам лучше использовать MTA, настроенный на отправку копий всего в архив, а также отправлять файлы на ваш IMAP-сервер. Если вам сложно это настроить, рассмотрите возможность использования сторонней службы, которая будет управлять вашими архивами и пересылать почту на ваш существующий почтовый сервер.

Если вы действительно хотите сделать это путем копирования из IMAP, я рекомендую посмотреть offlineimap .

Если вы действительно хотите сделать это самостоятельно, способ отследить уже просмотренные сообщения - использовать заголовок Message-ID.

...