ebf85694851071da95c6d6b8aec2e7f401338a2a
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

1) #!/usr/bin/python
2) 
3) import smtpd
4) import logging
5) import sys
6) import smtplib
7) import MantisMail
8) import MantisWS
9) import asyncore
10) import os
11) import signal
Benjamin Renard Added parameter to save rec...

Benjamin Renard authored 12 years ago

12) import time
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

13) 
14) class MantisSMTPServer(smtpd.SMTPServer):
15) 
16) 	_mail2project = {}
17) 
18) 	_options={}
19) 	_options['mail_from']='postmaster-mantis@example.net'
20) 	_options['smtp_host']='127.0.0.1'
21) 	_options['smtp_port']='25'
22) 	_options['ws_url']='http://mantis.example.net/api/soap/mantisconnect.php?wsdl'
23) 	_options['ws_user']='mantis'
24) 	_options['ws_pwd']='password'
25) 	_options['ws_default_category']='other'
Benjamin Renard Added parameter to save rec...

Benjamin Renard authored 12 years ago

26) 	_options['save_dir']=None
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

27) 
28) 	ws=None
29) 
30) 	_pidfile = None
31) 
32) 	def start(self):
33) 		logging.info('Start Mantis SMTP Server')
34) 		self._start()
35) 
36) 	def startDaemon(self,pidfile):
37) 		self._pidfile=pidfile
38) 		try:
39) 			pid = os.fork()
40) 			if pid > 0:
41) 				# Exit parent
42) 				sys.exit(0)
43) 		except OSError, e:
44) 			sys.stderr.write("Daemonize failed: %d (%s)\n" % (e.errno, e.strerror))
45)                         sys.exit(1)
46) 
47) 		logging.info('Start Mantis SMTP Server as daemon')
48) 		pid = str(os.getpid())
49) 		file(self._pidfile,'w+').write("%s\n" % pid)
50) 		signal.signal(signal.SIGTERM,self.stopDaemon)
51) 		self._start()
52) 
53) 	def stopDaemon(self,signum, frame):
54) 		logging.info('Stop Mantis SMTP Server by SIGTERM')
55) 		os.remove(self._pidfile)
56) 		sys.exit(0)
57) 		
58) 	def _start(self):
59) 		asyncore.loop()
60) 		
61) 	def stop(self):
62) 		logging.info('Stop Mantis SMTP Server')
63) 
64) 	def process_message(self, peer, mailfrom, rcpttos, data):
65) 
66) 		logging.info('Message receive from %s, send by %s to %s' % (peer,mailfrom,rcpttos))
Benjamin Renard Added parameter to save rec...

Benjamin Renard authored 12 years ago

67) 		self.save_msg(peer, mailfrom, rcpttos, data)
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

68) 		
69) 		try:
70) 			msg = MantisMail.MantisMail(mailfrom,rcpttos,data)
71) 		except:
72) 			logging.error('Error parsing message receive from %s, send by %s to %s : %s' % (peer,mailfrom,rcpttos,sys.exc_info()[0]))
73) 			return
74) 
75) 		issue_id=msg.get_issue_id_from_subject()
76) 
77) 		if issue_id:
78) 			logging.info("Answer to issue #%s" % issue_id)
79) 			self.add_note_to_issue_from_msg(msg)
80) 		else:
81) 			project_infos=self.get_mantis_project_infos_from_recipient(rcpttos)
82) 			if project_infos is None:
83) 				logging.warning("Unknown recipient : Can't determine project to create issue. This email can't be processed. Warning message will be send to sender.")
84) 				MantisMail.send(
85) 					self._options['mail_from'],
86) 					msg.mailfrom,
87) 					'[Mantis] Unknown recipient %s' % rcpttos[0],
88) 					"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.",
89) 					smtp_host=self._options['smtp_host'],
90) 					smtp_port=self._options['smtp_port']
91) 				)
92) 			else:
93) 				project=project_infos['project']
94) 				logging.info("New issue for project %s" % project)
95) 				self.add_new_issue_to_project_from_msg(project_infos,msg)
96)  
97) 		return
98) 
99) 	def add_project(self,email,project,category=None):
100) 		self._mail2project[email]={
101) 			'project':	project
102) 		}
103) 		if category is not None:
104) 			self._mail2project[email]['category']=category
105) 
106) 	def get_mantis_project_infos_from_recipient(self,tos):
107) 		for to in tos:
108) 			if to in self._mail2project:
109) 				return self._mail2project[to]
110) 		return None
111) 
112) 
113) 	def set_option(self,option,value):
114) 		if option in self._options:
115) 			self._options[option]=value
116) 
117) 	def start_ws(self):
118) 		self.ws=MantisWS.MantisWS(self._options['ws_url'],self._options['ws_user'],self._options['ws_pwd'])
119) 
120) 		self.ws.set_option('default_category',self._options['ws_default_category'])
121) 
122) 		for option in ['mail_from','smtp_host','smtp_port']:
123) 			self.ws.set_option(option,self._options[option])
124) 
125) 
126) 	def add_new_issue_to_project_from_msg(self,project_infos,msg):
127) 		if self.ws is None:
128) 			self.start_ws()
129) 		issue_id = self.ws.add_issue_to_project(msg.mailfrom,project_infos,msg.subject(),msg.get_text())
130) 		if issue_id:
131) 			logging.info('Issue added with id %s' % issue_id)
Benjamin Renard MantisSMTPServer : add usag...

Benjamin Renard authored 12 years ago

132) 			self.add_attachment_to_issue(issue_id,msg)
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

133) 			return issue_id
134) 		else:
135) 			logging.error('Error during add issue')
Benjamin Renard MantisSMTPServer : send ema...

Benjamin Renard authored 12 years ago

136) 			self.alert_sender(
137) 				msg,
138) 				u"[Mantis] Error occured adding your issue '%s'" % msg.subject(),
139) 				u"An error occured adding your issue :\n\nSubject : %s\n--\n%s" % (issue_id,msg.subject(),msg.get_text())
140) 			)
141) 
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

142) 
143) 	def add_note_to_issue_from_msg(self,msg):
144) 		if self.ws is None:
145) 			self.start_ws()
146) 
147) 		issue_id=msg.get_issue_id_from_subject()
Benjamin Renard MantisSMTPServer : create a...

Benjamin Renard authored 12 years ago

148) 		try:
149) 			note_id = self.ws.add_note_to_issue(issue_id,msg.get_text())
150) 			if note_id:
151) 				logging.info('Note add to issue %s with id %s' % (issue_id,note_id))
152) 				self.add_attachment_to_issue(issue_id,msg)
153) 				return issue_id
154) 			else:
155) 				logging.error('Error adding issue')
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

156) 
Benjamin Renard MantisSMTPServer : create a...

Benjamin Renard authored 12 years ago

157) 	def add_attachment_to_issue(self,issue_id,msg):
158) 		for attachment in msg.get_attachments():
159) 			try:
160) 				logging.info('Add attachment to issue %s : %s' % (issue_id,attachment['filename']))
161) 				self.ws.add_attachment_to_issue(issue_id,attachment)
162) 			except MantisWS.MantisWSError, e:
163) 				logging.error('MantisWS error adding attachment %s to issue %s : %s.' % (attachment['filename'],issue_id, e))
164) 
165) 			except Exception, e:
166) 				logging.error('Unknown error adding attachment %s to issue %s : %s. Warning sender by mail.' % (attachment['filename'],issue_id,e))
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

167) 
Benjamin Renard Added parameter to save rec...

Benjamin Renard authored 12 years ago

168) 
169) 	def save_msg(self,peer, mailfrom, rcpttos, data):
170) 		if self._options['save_dir']:
171) 			f="%s/%s" % (self._options['save_dir'],"%s-%s--%s--%s.msg" % (time.time(), peer[0],mailfrom,rcpttos[0]))
172) 			try:
173) 				logging.info('Save mail data into %s' % f)
174) 				fd=open(f,'w')
175) 				fd.write(data)
176) 				fd.close()
177) 			except Exception, e:
178) 				logging.error("Can't save message from %s to % receive from %s into %s : %s" % (mailfrom,rcpttos,peer,f,e))