2011-08-11 77 views
3

我们的办公室使用2个IMAP服务器进行电子邮件,一个是传入服务器并保存最近的电子邮件,另一个是归档服务器。我们主要使用Outlook 2010,而我们当前的过程是定期将发送的邮件从传入服务器拖动到存档。将邮件从一个IMAP服务器移动到另一个IMAP服务器的脚本

今天我被要求研究编写脚本,并定期(可能使用crontab)抓住所有发送的消息并将它们移动到归档。

我已经看过一些SSL或telnet访问服务器和周围的例子。但是,我不知道在IMAP环境中编写脚本或如何移动文件跨服务器的最佳方式。

完成此操作的最佳方法是什么?我宁愿仅仅从舒适的角度来使用Python,但如果已经有另一种语言的现有解决方案,我可以处理它。


更新:

好吧,这里是一些代码。目前它复制消息就好了,但是,它会复制存档服务器上的现有消息。

import imaplib 
import sys 

#copy from 
f_server = 'some.secret.ip.address' 
f_username = '[email protected]' 
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's Blog: imaplib - IMAP4 Client Library
Tyler Lesmann's Blog: Copying IMAP Mailboxes with Python and imaplib

我还需要:

  • 删除/直播服务器
  • 不可复制副本(在清除邮件实际上这将是通过复制后删除原件进行修复,但...)
  • 错误捕获

更新2:

人对如何不创建重复复印时,任何想法? (现在不包括删除原件的选项),我想过要搜索文本,但是意识到嵌套的回复可能会导致这种情况。

+0

rsync是从一个系统复制到另一个系统的选项吗? –

回答

3

这是我最终使用的。我不认为它是完美的,它使用msg_num而不是id的方式有点冒险。但是这是相当低的成交量,也许几个小时(在cron上)。

import imaplib 

#copy from 
from_server = {'server': '1.1.1.1', 
       'username': '[email protected]', 
       '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) 
0

我不确定你处理的邮件量是多少,但是你可以从每个邮件中提取Message-ID并使用它来确定它是否是重复邮件。每次准备移动消息时,都可以在目标服务器上生成一个ID列表,或者在归档时将它们添加到简单的数据库中。

如果查找过于昂贵,则可以通过其他消息属性缩小范围,例如Date,然后在不再需要时删除较旧的列表。

0

大概为时已晚,对OP有所帮助,但希望对任何以后的人都有用。

这看起来像一个通用的要求。你可能不应该自定义编码任何东西。

使用MTA配置为将所有内容的副本发送到存档以及将内容发送到您的IMAP服务器可能会更好。如果您难以设置,请考虑使用第三方服务,谁来管理您的档案,并将邮件转发到您现有的邮件服务器上。

如果你确实想通过从IMAP复制来做到这一点,我会建议看看offlineimap

如果你确实想自己做,跟踪你已经看到的消息的方式是使用消息ID头。

相关问题