5755a378ea461f8957ac8025048310d12cf5b0b7
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:
Benjamin Renard MantisSMTPServer : send ema...

Benjamin Renard authored 12 years ago

155) 				self.alert_sender(
156) 					msg,
157) 					u"[Mantis] Error occured adding your note to issue %s" % issue_id,
158) 					u"An error occured adding your note to issue %s. Your note has not been added.\n\nSubject : %s\n--\n%s" % (issue_id,msg.subject(),msg.get_text())
159) 				)
Benjamin Renard MantisSMTPServer : create a...

Benjamin Renard authored 12 years ago

160) 				logging.error('Error adding issue')
Benjamin Renard MantisSMTPServer : send ema...

Benjamin Renard authored 12 years ago

161) 		except MantisWS.MantisWSError, e:
162) 			if e.type == 'unknown_issue_note_add':
163) 				subject = u"[Mantis] Issue %s does not exists. Can't add your note." % issue_id
164) 				content = u"Issue %s does not exists. Can't add your note :\n\nSubject : %s\n--\n%s" % (issue_id,msg.subject(),msg.get_text())
165) 
166) 			else:
167) 				subject = u"[Mantis] WS error occured adding your note to issue %s" % issue_id
168)                                 content = u"An WS error occured adding your note to issue %s. Your note has not been added.\n\nSubject : %s\n--\n%s" % (issue_id,msg.subject(),msg.get_text())
169) 			self.alert_sender(
170) 				msg,
171) 				subject,
172) 				content
173) 			)
Benjamin Renard Initial commit

Benjamin Renard authored 12 years ago

174) 
Benjamin Renard MantisSMTPServer : create a...

Benjamin Renard authored 12 years ago

175) 	def add_attachment_to_issue(self,issue_id,msg):
176) 		for attachment in msg.get_attachments():
177) 			try:
178) 				logging.info('Add attachment to issue %s : %s' % (issue_id,attachment['filename']))
179) 				self.ws.add_attachment_to_issue(issue_id,attachment)
180) 			except MantisWS.MantisWSError, e:
181) 				logging.error('MantisWS error adding attachment %s to issue %s : %s.' % (attachment['filename'],issue_id, e))
182) 
183) 			except Exception, e:
184) 				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

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

Benjamin Renard authored 12 years ago

186) 
187) 	def save_msg(self,peer, mailfrom, rcpttos, data):
188) 		if self._options['save_dir']:
189) 			f="%s/%s" % (self._options['save_dir'],"%s-%s--%s--%s.msg" % (time.time(), peer[0],mailfrom,rcpttos[0]))
190) 			try:
191) 				logging.info('Save mail data into %s' % f)
192) 				fd=open(f,'w')
193) 				fd.write(data)
194) 				fd.close()
195) 			except Exception, e:
196) 				logging.error("Can't save message from %s to % receive from %s into %s : %s" % (mailfrom,rcpttos,peer,f,e))