簡體   English   中英

將消息從一個 IMAP 服務器移動到另一個的腳本

[英]Script to move messages from one IMAP server to another

我們的辦公室使用兩台 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()

一些資料來源:
Doug Hellman 的博客:imaplib - IMAP4 客戶端庫
Tyler Lesmann 的博客:使用 Python 和 imaplib 復制 IMAP 郵箱

我仍然需要:

  • 刪除/刪除實時服務器上的消息
  • 不復制副本(實際上這可以通過在復制后刪除原件來解決,但是......)
  • 錯誤捕獲

更新 2:

有人對復制時如何不創建重復項有任何想法嗎? (暫時不包括刪除原件的選項)我考慮過搜索文本,但意識到嵌套回復可能會將其排除在外。

這是我最終使用的。 我並不聲稱它是完美的,它使用 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)

我不確定您正在處理多少消息,但您可以從每條消息中提取Message-ID並使用它來確定它是否是重復的。 每次准備移動消息時,生成目標服務器上已有的 ID 列表,或者在歸檔時將它們添加到簡單的數據庫中。

如果查找過於昂貴,您可以通過附加消息屬性(如Date )來縮小范圍,然后在不再需要舊列表時刪除它們。

大概為時已晚,無法對 OP 有所幫助,但希望對以后跟隨的任何人都有用。

這看起來像一個通用要求。 您可能不應該自定義編碼任何東西。

您最好使用配置為將所有內容的副本發送到存檔以及將內容發送到 IMAP 服務器的 MTA。 如果這對您來說很難設置,請考慮使用第三方服務,該服務將管理您的檔案,並將郵件轉發到您現有的郵件服務器。

如果您確實想通過從 IMAP 復制來做到這一點,我建議您查看offlineimap

如果您確實想自己做,那么跟蹤您已經看到的消息的方法是使用 Message-ID header。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM