2010-08-20 13 views

Trả lời

33

Không có lệnh di chuyển rõ ràng cho IMAP. Bạn sẽ phải thực hiện một số COPY theo sau là STORE (có cờ phù hợp để biểu thị việc xóa) và cuối cùng là expunge. Ví dụ được đưa ra dưới đây hoạt động để di chuyển thư từ một nhãn sang nhãn khác. Có thể bạn sẽ muốn thêm nhiều kiểm tra lỗi hơn.

import imaplib, getpass, re 
pattern_uid = re.compile('\d+ \(UID (?P<uid>\d+)\)') 

def connect(email): 
    imap = imaplib.IMAP4_SSL("imap.gmail.com") 
    password = getpass.getpass("Enter your password: ") 
    imap.login(email, password) 
    return imap 

def disconnect(imap): 
    imap.logout() 

def parse_uid(data): 
    match = pattern_uid.match(data) 
    return match.group('uid') 

if __name__ == '__main__': 
    imap = connect('<your mail id>') 
    imap.select(mailbox = '<source folder>', readonly = False) 
    resp, items = imap.search(None, 'All') 
    email_ids = items[0].split() 
    latest_email_id = email_ids[-1] # Assuming that you are moving the latest email. 

    resp, data = imap.fetch(latest_email_id, "(UID)") 
    msg_uid = parse_uid(data[0]) 

    result = imap.uid('COPY', msg_uid, '<destination folder>') 

    if result[0] == 'OK': 
     mov, data = imap.uid('STORE', msg_uid , '+FLAGS', '(\Deleted)') 
     imap.expunge() 

    disconnect(imap) 
+2

Bất kỳ suy nghĩ nào về việc di chuyển nhiều thư? bạn có phải thực hiện tìm kiếm khác và nhận thư mới nhất với email_ids [-1] không? – ewalk

+3

Gmail IMAP * tự động * thực hiện '\ Deleted' /' EXPUNGE' cho bạn khi bạn 'COPY' gửi thư thành' [Gmail]/Thùng rác'. – dkarp

+0

@dkarp cảm ơn thông tin bạn đã cung cấp. Tôi đã cố gắng này từ 1 tuần qua. –

4

Tôi cho rằng có một địa chỉ email sẽ được di chuyển.

import imaplib 
obj = imaplib.IMAP4_SSL('imap.gmail.com', 993) 
obj.login('username', 'password') 
obj.select(src_folder_name) 
apply_lbl_msg = obj.uid('COPY', msg_uid, desti_folder_name) 
if apply_lbl_msg[0] == 'OK': 
    mov, data = obj.uid('STORE', msg_uid , '+FLAGS', '(\Deleted)') 
    obj.expunge() 
4

Đối với Gmail, dựa trên api working with labels của nó, điều duy nhất để bạn có thể làm là thêm nhãn đích và xóa nhãn src:

import imaplib 
obj = imaplib.IMAP4_SSL('imap.gmail.com', 993) 
obj.login('username', 'password') 
obj.select(src_folder_name) 
typ, data = obj.uid('STORE', msg_uid, '+X-GM-LABELS', desti_folder_name) 
typ, data = obj.uid('STORE', msg_uid, '-X-GM-LABELS', src_folder_name) 
+0

Điều này không hiệu quả đối với tôi. Nó đã thêm nhãn desti_folder_name, nhưng nó không loại bỏ nhãn src_folder_name. Tuy nhiên, giải pháp của Manoj Govindan đã làm việc cho tôi. – mernst

+0

Tôi có thể xác nhận tương tự, nhưng tại sao việc xóa không hoạt động? Giải pháp chính xác là gì? – sorin

+0

@sorin này hoạt động cho tôi, bạn có thể đang làm điều gì sai. Tôi đã làm nó ngay bây giờ sau tất cả các bước theo dòng ... – scraplesh

3

Không ai trong số các giải pháp trước đó từng làm việc cho tôi. Tôi không thể xóa thư từ thư mục đã chọn và không thể xóa nhãn cho thư mục khi nhãn là thư mục đã chọn. Dưới đây là những gì đã kết thúc với tôi:

import email, getpass, imaplib, os, sys, re 

user = "[email protected]" 
pwd = "password" #getpass.getpass("Enter your password: ") 

m = imaplib.IMAP4_SSL("imap.gmail.com") 
m.login(user,pwd) 

from_folder = "Notes" 
to_folder = "food" 

m.select(from_folder, readonly = False) 

response, emailids = imap.search(None, 'All') 
assert response == 'OK' 

emailids = emailids[0].split() 

errors = [] 
labeled = [] 
for emailid in emailids: 
    result = m.fetch(emailid, '(X-GM-MSGID)') 
    if result[0] != 'OK': 
     errors.append(emailid) 
     continue 

    gm_msgid = re.findall(r"X-GM-MSGID (\d+)", result[1][0])[0] 

    result = m.store(emailid, '+X-GM-LABELS', to_folder) 

    if result[0] != 'OK': 
     errors.append(emailid) 
     continue 

    labeled.append(gm_msgid) 

m.close() 
m.select(to_folder, readonly = False) 

errors2 = [] 

for gm_msgid in labeled: 
    result = m.search(None, '(X-GM-MSGID "%s")' % gm_msgid) 

    if result[0] != 'OK': 
     errors2.append(gm_msgid) 
     continue 

    emailid = result[1][0] 
    result = m.store(emailid, '-X-GM-LABELS', from_folder) 

    if result[0] != 'OK': 
     errors2.append(gm_msgid) 
     continue 

m.close() 
m.logout() 

if errors: print >>sys.stderr, len(errors), "failed to add label", to_folder 
if errors2: print >>sys.stderr, len(errors2), "failed to remove label", from_folder 
0

Tôi biết rằng đây là một câu hỏi rất cũ, nhưng bất kỳ cách nào. Giải pháp được đề xuất bởi Manoj Govindan có thể hoạt động hoàn hảo (tôi chưa thử nghiệm nhưng có vẻ như nó. Vấn đề mà tôi gặp phải và tôi phải giải quyết là cách sao chép/di chuyển nhiều hơn một email !!!

Vì vậy, tôi đã đến

Các bước đơn giản, tôi kết nối với tài khoản email của tôi (GMAIL) chọn thư mục để xử lý (ví dụ INBOX) tìm nạp tất cả các uids, thay vì email (Đây là một điểm quan trọng cần lưu ý ở đây Nếu chúng tôi lấy số danh sách email và sau đó chúng tôi đã xử lý danh sách chúng tôi sẽ gặp phải sự cố. Khi chúng tôi chuyển email, quá trình này rất đơn giản (sao chép tại đích và xóa email từ từng vị trí hiện tại). Sự cố xuất hiện nếu bạn có danh sách email, ví dụ: 4 email bên trong hộp thư đến và chúng tôi xử lý email thứ 2 trong danh sách sau đó số 3 và 4 khác nhau, chúng không phải là email mà chúng tôi cho là chúng sẽ bị lỗi vì mục danh sách số 4 sẽ không tồn tại vì danh sách đã di chuyển một vị trí xuống vì 2 vị trí trống.

Vì vậy, giải pháp duy nhất có thể cho vấn đề này là sử dụng UID. Đó là số duy nhất cho mỗi email. Vì vậy, không có vấn đề làm thế nào email sẽ thay đổi số này sẽ được ràng buộc với email. Vì vậy, trong ví dụ bên dưới, tôi tìm nạp UID ở bước đầu tiên, kiểm tra xem thư mục có trống không có điểm xử lý thư mục khác lặp lại cho tất cả các email được tìm thấy trong thư mục hay không. Tiếp theo tìm nạp từng Tiêu đề email. Tiêu đề sẽ giúp chúng tôi tìm nạp Chủ đề và so sánh chủ đề của email với chủ đề mà chúng tôi đang tìm kiếm. Nếu chủ đề phù hợp, sau đó tiếp tục sao chép và xóa email. Sau đó bạn đã xong. Đơn giản như thế.

#!/usr/bin/env python 

import email 
import pprint 
import imaplib 

__author__ = 'author' 


def initialization_process(user_name, user_password, folder): 
    imap4 = imaplib.IMAP4_SSL('imap.gmail.com') # Connects over an SSL encrypted socket 
    imap4.login(user_name, user_password) 
    imap4.list() # List of "folders" aka labels in gmail 
    imap4.select(folder) # Default INBOX folder alternative select('FOLDER') 
    return imap4 


def logout_process(imap4): 
    imap4.close() 
    imap4.logout() 
    return 


def main(user_email, user_pass, scan_folder, subject_match, destination_folder): 
    try: 
     imap4 = initialization_process(user_email, user_pass, scan_folder) 
     result, items = imap4.uid('search', None, "ALL") # search and return uids 
     dictionary = {} 
     if items == ['']: 
      dictionary[scan_folder] = 'Is Empty' 
     else: 
      for uid in items[0].split(): # Each uid is a space separated string 
       dictionary[uid] = {'MESSAGE BODY': None, 'BOOKING': None, 'SUBJECT': None, 'RESULT': None} 
       result, header = imap4.uid('fetch', uid, '(UID BODY[HEADER])') 
       if result != 'OK': 
        raise Exception('Can not retrieve "Header" from EMAIL: {}'.format(uid)) 
       subject = email.message_from_string(header[0][1]) 
       subject = subject['Subject'] 
       if subject is None: 
        dictionary[uid]['SUBJECT'] = '(no subject)' 
       else: 
        dictionary[uid]['SUBJECT'] = subject 
       if subject_match in dictionary[uid]['SUBJECT']: 
        result, body = imap4.uid('fetch', uid, '(UID BODY[TEXT])') 
        if result != 'OK': 
         raise Exception('Can not retrieve "Body" from EMAIL: {}'.format(uid)) 
        dictionary[uid]['MESSAGE BODY'] = body[0][1] 
        list_body = dictionary[uid]['MESSAGE BODY'].splitlines() 
        result, copy = imap4.uid('COPY', uid, destination_folder) 
        if result == 'OK': 
         dictionary[uid]['RESULT'] = 'COPIED' 
         result, delete = imap4.uid('STORE', uid, '+FLAGS', '(\Deleted)') 
         imap4.expunge() 
         if result == 'OK': 
          dictionary[uid]['RESULT'] = 'COPIED/DELETED' 
         elif result != 'OK': 
          dictionary[uid]['RESULT'] = 'ERROR' 
          continue 
        elif result != 'OK': 
         dictionary[uid]['RESULT'] = 'ERROR' 
         continue 
       else: 
        print "Do something with not matching emails" 
        # do something else instead of copy 
      dictionary = {scan_folder: dictionary} 
    except imaplib.IMAP4.error as e: 
     print("Error, {}".format(e)) 
    except Exception as e: 
     print("Error, {}".format(e)) 
    finally: 
     logout_process(imap4) 
     return dictionary 

if __name__ == "__main__": 
    username = '[email protected]' 
    password = 'examplePassword' 
    main_dictionary = main(username, password, 'INBOX', 'BOKNING', 'TMP_FOLDER') 
    pprint.pprint(main_dictionary) 
    exit(0) 

Thông tin hữu ích về imaplib Python — imaplib IMAP example with Gmailimaplib documentation.