aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVosjedev <vosje@vosjedev.net>2025-11-02 15:41:45 +0100
committerVosjedev <vosje@vosjedev.net>2025-11-02 15:41:45 +0100
commit8bcffee40c893a8b4a46ba17275f89d7d55ed9ab (patch)
treeafd2aa3ac0b0eec3a0c068731182eabbecd4ff14
parent82ec0feb048511f8c48648d42f251bdada372b39 (diff)
downloadacit-8bcffee40c893a8b4a46ba17275f89d7d55ed9ab.tar.gz
acit-8bcffee40c893a8b4a46ba17275f89d7d55ed9ab.tar.bz2
acit-8bcffee40c893a8b4a46ba17275f89d7d55ed9ab.tar.xz
imapplugin.py: Move handling email to own function
-rw-r--r--src/acit/imapplugin.py168
1 files changed, 89 insertions, 79 deletions
diff --git a/src/acit/imapplugin.py b/src/acit/imapplugin.py
index 454904d..6bee54b 100644
--- a/src/acit/imapplugin.py
+++ b/src/acit/imapplugin.py
@@ -204,99 +204,109 @@ class ImapPlugin(plugins.SimplePlugin):
if mailbox.folder.status()["MESSAGES"]>0:
for msg in mailbox.fetch():
- self.mlog("Processing email with subject '%s'"%msg.subject)
+ target=self.handle_email(mailbox,msg)
+ if target:
+ proj,bug=target
+ refreshable.setdefault(proj,[]).append(bug)
+ # block: update all webpages that received new mail
+ for proj,bugs in refreshable.items():
+ # project page needs to be regenerated too (counters)
+ cherrypy.engine.publish("regen",proj,None)
+ for bug in bugs:
+ cherrypy.engine.publish("regen",proj,bug)
- for addr in msg.to + msg.cc + msg.bcc + msg.reply_to:
- if re.fullmatch(self.addr_regex,addr):
- proj,bug=self.stripInfoFromMailAddr(addr)
- break
- else:
- proj=None
- bug=None
+ # end block
- if "in-reply-to" in msg.headers:
- self.mlog("Using In-Reply-To header to figure out meta")
- replyid=msg.headers["in-reply-to"]
- data=self.find_in_reply_to(replyid)
- if data:
- proj,bug=data
+ if refreshable:
+ self.update_index([proj,bug] for bug in bugs for proj,bugs in refreshable.items())
- # block: make sure a project was specified
- if not proj:
- self.mlog("No project specified.")
- self.mail_error(msg,"Please specify a project by mailing to:\n "+\
- ("" if self.uses_aliases else self.emailname+"+")+"PROJECT@"+self.emaildomain+\
- "\nwhere PROJECT is the name of your target project")
- self.move_errored_mail(mailbox,msg)
- continue
- # end block
+ def handle_email(self,mailbox:MailBox,msg:MailMessage):
+ self.mlog("Processing email with subject '%s'"%msg.subject)
- # block: make sure project exists
- proj_matches=self.get_full_projectname(proj)
- if not proj_matches:
- self.mlog("Received email for nonexistent project %s"%proj)
- self.mail_error(msg,notice="Project '%s' doesn't exist"%proj)
- self.move_errored_mail(mailbox,msg)
- continue
- # end block
- # block: make sure only 1 project matches
- if len(proj_matches)>1:
- self.mlog("Conficting projectname. Sending projectlist.")
- self.mail_error(msg,notice="Multiple projects found to match your query. Please specify. Options:\n%s"%"\n".join(proj_matches))
- self.move_errored_mail(mailbox,msg)
- continue
+ for addr in msg.to + msg.cc + msg.bcc + msg.reply_to:
+ if re.fullmatch(self.addr_regex,addr):
+ proj,bug=self.stripInfoFromMailAddr(addr)
+ break
+ else:
+ proj=None
+ bug=None
- proj=proj_matches[0]
- # end block
+ if "in-reply-to" in msg.headers:
+ self.mlog("Using In-Reply-To header to figure out meta")
+ replyid=msg.headers["in-reply-to"]
+ data=self.find_in_reply_to(replyid)
+ if data:
+ proj,bug=data
+ else: # try again later, maybe we need to index first or handle some other email first
+ self.mlog("Message-ID not in index, trying again next round")
+ return
- # block: parse bug id
- if not bug:
- if re.match(r"^\[PATCH.*\]",msg.subject):
- bugtype="PATCH"
- elif re.match(r"^\[DISCUSSION.*\]",msg.subject):
- bugtype="DISCUS"
- else:
- bugtype="BUG"
- bug=self.site.newbug(proj,bugtype=bugtype)
- bug.subject=msg.subject[:1024]
- bug.description=\
- 'No description written.\nFirst email in thread:\n\n'+msg.text[:65535] # TODO: don't thruncate silently, send error to user.
- self.mlog("Assigned new bugnr %d to '%s'"%(bug.bugid,msg.subject))
- bug=bug.bugid
+ # block: make sure a project was specified
+ if not proj:
+ self.mlog("No project specified.")
+ self.mail_error(msg,"Please specify a project by mailing to:\n "+\
+ ("" if self.uses_aliases else self.emailname+"+")+"PROJECT@"+self.emaildomain+\
+ "\nwhere PROJECT is the name of your target project")
+ self.move_errored_mail(mailbox,msg)
+ return
+ # end block
- try:
- bug=int(bug)
- except ValueError as e:
- self.mlog("Error decoding value to int:",e,traceback=True)
+ # block: make sure project exists
+ proj_matches=self.get_full_projectname(proj)
+ if not proj_matches:
+ self.mlog("Received email for nonexistent project %s"%proj)
+ self.mail_error(msg,notice="Project '%s' doesn't exist"%proj)
+ self.move_errored_mail(mailbox,msg)
+ return
+ # end block
- self.mail_error(msg,notice="Exception while trying to convert bug number to integer",exception=e)
- self.move_errored_mail(mailbox,msg)
- continue
- # end block
-
- # block: move mail to folder specific for this project/bug
- try:
- path=self.get_bug_folder(mailbox,proj,bug)
- mailbox.move([msg.uid], path)
- refreshable.setdefault(proj,[]).append(bug)
- except Exception:
- self.mlog("Error processing email '%s' for %s/%d"%(msg.subject,proj,bug),traceback=True)
- # end block
+ # block: make sure only 1 project matches
+ if len(proj_matches)>1:
+ self.mlog("Conficting projectname. Sending projectlist.")
+ self.mail_error(msg,notice="Multiple projects found to match your query. Please specify. Options:\n%s"%"\n".join(proj_matches))
+ self.move_errored_mail(mailbox,msg)
+ return
- # block: update all webpages that received new mail
- for proj,bugs in refreshable.items():
- # project page needs to be regenerated too (counters)
- cherrypy.engine.publish("regen",proj,None)
- for bug in bugs:
- cherrypy.engine.publish("regen",proj,bug)
+ proj=proj_matches[0]
+ # end block
- # end block
+ # block: parse bug id
+ if not bug:
+ if re.match(r"^\[PATCH.*\]",msg.subject):
+ bugtype="PATCH"
+ elif re.match(r"^\[DISCUSSION.*\]",msg.subject):
+ bugtype="DISCUS"
+ else:
+ bugtype="BUG"
+ bug=self.site.newbug(proj,bugtype=bugtype)
+ bug.subject=msg.subject[:1024]
+ bug.description=\
+ 'No description written.\nFirst email in thread:\n\n'+msg.text[:65535] # TODO: don't thruncate silently, send error to user.
+ self.mlog("Assigned new bugnr %d to '%s'"%(bug.bugid,msg.subject))
+ bug=bug.bugid
- if refreshable:
- self.update_index([proj,bug] for bug in bugs for proj,bugs in refreshable.items())
+ try:
+ bug=int(bug)
+ except ValueError as e:
+ self.mlog("Error decoding value to int:",e,traceback=True)
+ self.mail_error(msg,notice="Exception while trying to convert bug number to integer",exception=e)
+ self.move_errored_mail(mailbox,msg)
+ return
+ # end block
+
+ # block: move mail to folder specific for this project/bug
+ self.mlog("Email '%s' into %s/%d"%(msg.subject,proj,bug))
+ try:
+ path=self.get_bug_folder(mailbox,proj,bug)
+ mailbox.move([msg.uid], path)
+ except Exception:
+ self.mlog("Error processing email '%s' for %s/%d"%(msg.subject,proj,bug),traceback=True)
+ # end block
+
+ return (proj,bug)
def imap_loop_controller(self):
"Responsible for running imap_magic() repeatedly, and handling its errors."