8aae0bde7225aeebb27b633176226aa9112448a3
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)
132) 			return issue_id
133) 		else:
134) 			logging.error('Error during add issue')
135) 
136) 	def add_note_to_issue_from_msg(self,msg):
137) 		if self.ws is None:
138) 			self.start_ws()
139) 
140) 		issue_id=msg.get_issue_id_from_subject()
141) 
142) 		note_id = self.ws.add_note_to_issue(issue_id,msg.get_text())
143) 		if note_id:
144) 			logging.info('Note add to issue %s with id %s' % (issue_id,note_id))
145) 
146) 			for attachment in msg.get_attachments():
147) 				try:
148) 					logging.info('Add attachment to issue %s : %s' % (issue_id,attachment['filename']))
149) 					self.ws.add_attachment_to_issue(issue_id,attachment)
150) 				except MantisWS.MantisWSError, e:
151) 					if e.type == 'duplicate_attachment_filename':
152) 						logging.error('Duplicate filename %s in issue %s. Warning sender by mail.' % (attachment['filename'],issue_id))
153) 						MantisMail.send(
154) 							self._options['mail_from'],
155) 							msg.mailfrom,
156) 							'[Mantis] Duplicate filename %s in issue %s' % (attachment['filename'],issue_id),
157) 							"Your file %s attach in your email '%s' can't be attached to Mantis issue %s because a file with the same name is currently attached to this issue." % (attachment['filename'],msg.subject(),issue_id),
158) 							smtp_host=self._options['smtp_host'],
159) 							smtp_port=self._options['smtp_port']
160) 						)
161) 	
162) 				except:
163) 					logging.error('Error adding attachment %s to issue %s' % (attachment['filename'],issue_id))
164) #				
165) 
166) 			return issue_id
167) 		else:
168) 			logging.error('Error during add issue')