#!/usr/bin/python import smtpd import logging import sys import smtplib import MantisMail import MantisWS import asyncore import os import signal import time class MantisSMTPServer(smtpd.SMTPServer): _mail2project = {} _options={} _options['mail_from']='postmaster-mantis@example.net' _options['smtp_host']='127.0.0.1' _options['smtp_port']='25' _options['ws_url']='http://mantis.example.net/api/soap/mantisconnect.php?wsdl' _options['ws_user']='mantis' _options['ws_pwd']='password' _options['ws_default_category']='other' _options['save_dir']=None ws=None _pidfile = None def start(self): logging.info('Start Mantis SMTP Server') self._start() def startDaemon(self,pidfile): self._pidfile=pidfile try: pid = os.fork() if pid > 0: # Exit parent sys.exit(0) except OSError, e: sys.stderr.write("Daemonize failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) logging.info('Start Mantis SMTP Server as daemon') pid = str(os.getpid()) file(self._pidfile,'w+').write("%s\n" % pid) signal.signal(signal.SIGTERM,self.stopDaemon) self._start() def stopDaemon(self,signum, frame): logging.info('Stop Mantis SMTP Server by SIGTERM') os.remove(self._pidfile) sys.exit(0) def _start(self): asyncore.loop() def stop(self): logging.info('Stop Mantis SMTP Server') def process_message(self, peer, mailfrom, rcpttos, data): logging.info('Message receive from %s, send by %s to %s' % (peer,mailfrom,rcpttos)) self.save_msg(peer, mailfrom, rcpttos, data) try: msg = MantisMail.MantisMail(mailfrom,rcpttos,data) except: logging.error('Error parsing message receive from %s, send by %s to %s : %s' % (peer,mailfrom,rcpttos,sys.exc_info()[0])) return issue_id=msg.get_issue_id_from_subject() if issue_id: logging.info("Answer to issue #%s" % issue_id) self.add_note_to_issue_from_msg(msg) else: project_infos=self.get_mantis_project_infos_from_recipient(rcpttos) if project_infos is None: logging.warning("Unknown recipient : Can't determine project to create issue. This email can't be processed. Warning message will be send to sender.") MantisMail.send( self._options['mail_from'], msg.mailfrom, '[Mantis] Unknown recipient %s' % rcpttos[0], "Your email can't be inserted in Mantis because the recipient address of your message can't be recognized.\n\nPlease call your system administrator.", smtp_host=self._options['smtp_host'], smtp_port=self._options['smtp_port'] ) else: project=project_infos['project'] logging.info("New issue for project %s" % project) self.add_new_issue_to_project_from_msg(project_infos,msg) return def add_project(self,email,project,category=None): self._mail2project[email]={ 'project': project } if category is not None: self._mail2project[email]['category']=category def get_mantis_project_infos_from_recipient(self,tos): for to in tos: if to in self._mail2project: return self._mail2project[to] return None def set_option(self,option,value): if option in self._options: self._options[option]=value def start_ws(self): self.ws=MantisWS.MantisWS(self._options['ws_url'],self._options['ws_user'],self._options['ws_pwd']) self.ws.set_option('default_category',self._options['ws_default_category']) for option in ['mail_from','smtp_host','smtp_port']: self.ws.set_option(option,self._options[option]) def add_new_issue_to_project_from_msg(self,project_infos,msg): if self.ws is None: self.start_ws() issue_id = self.ws.add_issue_to_project(msg.mailfrom,project_infos,msg.subject(),msg.get_text()) if issue_id: logging.info('Issue added with id %s' % issue_id) return issue_id else: logging.error('Error during add issue') def add_note_to_issue_from_msg(self,msg): if self.ws is None: self.start_ws() issue_id=msg.get_issue_id_from_subject() try: note_id = self.ws.add_note_to_issue(issue_id,msg.get_text()) if note_id: logging.info('Note add to issue %s with id %s' % (issue_id,note_id)) self.add_attachment_to_issue(issue_id,msg) return issue_id else: logging.error('Error adding issue') def add_attachment_to_issue(self,issue_id,msg): for attachment in msg.get_attachments(): try: logging.info('Add attachment to issue %s : %s' % (issue_id,attachment['filename'])) self.ws.add_attachment_to_issue(issue_id,attachment) except MantisWS.MantisWSError, e: logging.error('MantisWS error adding attachment %s to issue %s : %s.' % (attachment['filename'],issue_id, e)) except Exception, e: logging.error('Unknown error adding attachment %s to issue %s : %s. Warning sender by mail.' % (attachment['filename'],issue_id,e)) def save_msg(self,peer, mailfrom, rcpttos, data): if self._options['save_dir']: f="%s/%s" % (self._options['save_dir'],"%s-%s--%s--%s.msg" % (time.time(), peer[0],mailfrom,rcpttos[0])) try: logging.info('Save mail data into %s' % f) fd=open(f,'w') fd.write(data) fd.close() except Exception, e: logging.error("Can't save message from %s to % receive from %s into %s : %s" % (mailfrom,rcpttos,peer,f,e))