[英]Script to move messages from one IMAP server to another
Our office uses 2 IMAP servers for e-mail, one is the incoming server and holds the recent e-mails and the other is an archive server.我们的办公室使用两台 IMAP 服务器来处理电子邮件,一台是接收服务器,保存最近的电子邮件,另一台是存档服务器。 We mainly use Outlook 2010 and our current process is to periodically drag sent messages from the incoming server to the archive.我们主要使用 Outlook 2010 并且我们当前的过程是定期将发送的消息从传入服务器拖到存档中。
Today I was asked into looking into writing a script and that would periodically (probably using crontab) grab all sent messages and move them to archive.今天我被要求研究编写一个脚本,它会定期(可能使用 crontab)抓取所有发送的消息并将它们移动到存档。
I've looked into some example of SSL or telnet to access the server and poke around.我研究了一些 SSL 或 telnet 的示例来访问服务器并四处寻找。 However I don't know the best way to script this or how to move files cross server within the IMAP environment.但是,我不知道编写此脚本的最佳方式或如何在 IMAP 环境中跨服务器移动文件。
What's the best way to accomplish this?实现这一目标的最佳方法是什么? I'd prefer to use Python just from comfort level, but if there is already an existing solution in another language, I could deal with it.我更喜欢使用 Python 只是从舒适的角度来看,但如果已经有另一种语言的现有解决方案,我可以处理它。
Update:更新:
Ok, here's some code.好的,这里有一些代码。 Currently It copies the messages just fine, however, it will duplicate exisiting messages on the archive server.目前它可以很好地复制邮件,但是,它将复制存档服务器上的现有邮件。
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()
Some sources:一些资料来源:
Doug Hellman's Blog: imaplib - IMAP4 Client Library Doug Hellman 的博客:imaplib - IMAP4 客户端库
Tyler Lesmann's Blog: Copying IMAP Mailboxes with Python and imaplib Tyler Lesmann 的博客:使用 Python 和 imaplib 复制 IMAP 邮箱
I still need to:我仍然需要:
Update 2:更新 2:
Anyone have any ideas on how to not create duplicates when copying?有人对复制时如何不创建重复项有任何想法吗? (excluding the option of deleting originals, for now) I thought about searching text, but realized nested replies could throw that off. (暂时不包括删除原件的选项)我考虑过搜索文本,但意识到嵌套回复可能会将其排除在外。
Here's what I ended up using.这是我最终使用的。 I don't claim that it's perfect, the way it uses msg_num and not id is a little risky.我并不声称它是完美的,它使用 msg_num 而不是 id 的方式有点冒险。 But this is fairly low volume moves, maybe a couple an hour (on cron).但这是相当低的交易量,可能一个小时(在 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)
I'm not sure what volume of messages you're dealing with, but you could extract the Message-ID
from each one and use that to find out if it's a duplicate.我不确定您正在处理多少消息,但您可以从每条消息中提取Message-ID
并使用它来确定它是否是重复的。 Either generate a list of IDs already on the target server each time you prepare to move messages, or add them to a simple database as they are archived.每次准备移动消息时,生成目标服务器上已有的 ID 列表,或者在归档时将它们添加到简单的数据库中。
You could narrow things down by an additional message property like Date
if the lookups are too expensive, then drop the older lists when you no longer need them.如果查找过于昂贵,您可以通过附加消息属性(如Date
)来缩小范围,然后在不再需要旧列表时删除它们。
Presumably too late to be helpful to the OP, but hopefully useful for anyone following along after now.大概为时已晚,无法对 OP 有所帮助,但希望对以后跟随的任何人都有用。
This looks like a generic requirement.这看起来像一个通用要求。 You probably shouldn't be custom coding anything.您可能不应该自定义编码任何东西。
You would probably be better off using an MTA configured to send copies of everything to an archive as well as sending stuff to your IMAP server.您最好使用配置为将所有内容的副本发送到存档以及将内容发送到 IMAP 服务器的 MTA。 If this is hard for you to set up, consider using a third party service, who would manage your archives, and forward mail on to your existing mail server.如果这对您来说很难设置,请考虑使用第三方服务,该服务将管理您的档案,并将邮件转发到您现有的邮件服务器。
If you really do want to do this by copying from IMAP, I'd suggest looking at offlineimap .如果您确实想通过从 IMAP 复制来做到这一点,我建议您查看offlineimap 。
If you really do want to do it yourself, the way to track the messages you've already seen is by using the Message-ID header.如果您确实想自己做,那么跟踪您已经看到的消息的方法是使用 Message-ID header。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.