1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#!/usr/bin/python
from bin import django_setup, add_logging_arguments
import email
import logging
import imaplib
django_setup() # must be called to get sys.path and django settings in place
from django.db import IntegrityError
from django.conf import settings
from django.utils.module_loading import import_string
from patchwork import parser
from patchwork.models import Patch, State
import patch_matcher
log = logging.getLogger('import_emails')
def find_old_revisions(patch):
log.debug('looking for old versions of patch %d', patch.id)
it = patch_matcher.get_patches_matching(
patch.project, [patch.submitter], patch.name, patch.diff)
for p in it:
# skip ourself
if p.id != patch.id:
yield p
def process_message(msg):
msg = email.message_from_string(msg)
log.info('subject: %s', msg.get('Subject'))
p = None
try:
p = parser.parse_mail(msg)
except IntegrityError as e:
log.info(e)
if p:
log.info('saved mail: %d', p.id)
for patch in Patch.objects.filter(msgid=p.msgid):
for old in find_old_revisions(patch):
log.info('marking patch %d as superseded by %d',
old.id, patch.id)
old.state = State.objects.get(name='Superseded')
old.save()
return p
def move_message(mail, uid, folder):
# put in proper folder and move out of inbox
status, _ = mail.uid('copy', uid, folder)
assert status == 'OK'
status, _ = mail.uid('store', uid, '+FLAGS', r'(\Deleted)')
assert status == 'OK'
def process_inbox(mail, max_messages=0):
status, _ = mail.select('inbox')
assert status == 'OK'
status, uids = mail.uid('search', None, 'ALL')
assert status == 'OK'
uids = uids[0].split()
if max_messages > 0:
uids = uids[:max_messages]
log.info('processing %d messages', len(uids))
added = processed = 0
for uid in uids:
try:
log.info('processing message: %s', uid)
status, data = mail.uid('fetch', uid, '(RFC822)')
assert status == 'OK'
if process_message(data[0][1]):
added += 1
move_message(mail, uid, 'processed')
processed += 1
except Exception:
log.exception('Unknown error for %s, moving to retry folder', uid)
move_message(mail, uid, 'retry')
break
log.info('processed %d messages, added %d', processed, added)
def get_monkey_patcher():
p = getattr(settings, 'PARSEMAIL_MONKEY_PATCHER', None)
if p:
return import_string(p)
if __name__ == '__main__':
import argparse
arg_parser = argparse.ArgumentParser(
description='Check configured inbox for new patches to import')
arg_parser.add_argument('--num-emails', type=int, default=80,
help='''Maximum number of emails to analyze.
default=%(default)d''')
add_logging_arguments(arg_parser)
args = arg_parser.parse_args()
parser.logger = log
mail = imaplib.IMAP4_SSL(settings.IMAP_SERVER)
status, _ = mail.login(settings.IMAP_USER, settings.IMAP_PASS)
assert status == 'OK'
monkey_patcher = get_monkey_patcher()
if monkey_patcher:
with monkey_patcher(parser):
process_inbox(mail, args.num_emails)
else:
process_inbox(mail, args.num_emails)
|