Подтвердить что ты не робот

Перемещение электронной почты в GMail с помощью Python и imaplib

Я хочу, чтобы иметь возможность переместить электронное письмо в GMail из папки "Входящие" в другую папку с помощью Python. Я использую imaplib и не могу понять, как это сделать.

4b9b3361

Ответ 1

Нет явной команды перемещения для IMAP. Вам нужно будет выполнить COPY, за которым следует STORE (с подходящим флагом для указания удаления) и, наконец, expunge. Приведенный ниже пример работал для перемещения сообщений с одной метки на другую. Вероятно, вы захотите добавить дополнительную проверку ошибок.

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

Я предполагаю, что у вас есть uid письма, которое будет перемещено.

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()

Ответ 3

Что касается Gmail, на основе api, работающего с ярлыками, единственное, что вам нужно сделать, это добавить ярлык dest и удалить ярлык 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)

Ответ 4

Ни один из предыдущих решений не работал у меня. Мне не удалось удалить сообщение из выбранной папки и не удалось удалить метку для папки, когда метка была выбрана. Здесь то, что в конечном итоге работает для меня:

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

Ответ 5

Я знаю, что это очень старый вопрос, но каким-то образом. Предлагаемое решение Manoj Govindan, вероятно, отлично работает (я его не тестировал, но похоже, что проблема. Я столкнулся с проблемой, и мне пришлось решить, как скопировать/переместить более одного письма!!!

Итак, я придумал решение, возможно, у кого-то в будущем может быть такая же проблема.

Шаги просты, я подключаюсь к моей учетной записи электронной почты (GMAIL), чтобы выбрать папку для обработки (например, INBOX), для получения всех uid вместо номера списка адресов электронной почты. Это важный момент, чтобы заметить здесь. Если мы выберем число адресов электронной почты, а затем обработаем список, у нас возникнет проблема. Когда мы перемещаем электронное письмо, процесс прост (скопируйте в папку назначения и удалите электронную почту из каждого текущего местоположения). Проблема возникает, если у вас есть список писем, например. 4 письма внутри почтового ящика, и мы обрабатываем 2-й адрес электронной почты внутри списка, а номера 3 и 4 отличаются друг от друга, это не письма, которые, по нашему мнению, были бы такими, что приведет к ошибке, поскольку элемент списка 4 не будет существуют, поскольку список сдвинул одну позицию вниз, потому что 2 позиции были пустыми.

Таким образом, единственным возможным решением этой проблемы было использование UID. Каковы уникальные номера для каждого письма. Поэтому, независимо от того, как изменится адрес электронной почты, это число будет привязано к электронной почте.

Итак, в приведенном ниже примере я набираю UID на первом шаге, проверяю, не является ли папка пустой, не имеет смысла обрабатывать папку, итерацию для всех электронных писем, найденных в папке. Затем введите каждый заголовок сообщения. Заголовки помогут нам получить тему и сравнить тему электронной почты с тем, что мы ищем. Если объект совпадает, продолжите копирование и удаление электронной почты. Тогда все готово. Просто как это.

#!/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)

Полезная информация относительно imaplib Пример Python - imaplib IMAP с Gmail и imaplib.