I wrote Smtp-Xmpp Transporter by python.
Anybody need this?
This implementation has a security issue.
Only AUTH PLAIN is supported.
set your jabber server information
130: self.__xmpp_domain = 'xmppserver'
131: self.__xmpp_server = '192.168.1.1'
132: self.__xmpp_port = 5222
----------
# coding: UTF-8
import smtpd
import base64
import xmpp
""" by t.yanagiwara 2010 Feb 21
"""
__all__ = ['SmtpXmppGw', 'SMTPXMPPGateway']
__version__ = 'smtp-xmppGW 0.1';
class ESMTPServer(smtpd.SMTPServer):
def handle_accept(self):
"""Override
"""
conn, addr = self.accept()
print >> smtpd.DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
channel = ESMTPChannel(self, conn, addr)
def process_auth(self, username, password):
raise NotImplementedError
def disconnect(self):
pass
class ESMTPChannel(smtpd.SMTPChannel):
AUTH = 2
def __init__(self, server, conn, addr):
smtpd.asynchat.async_chat.__init__(self, conn)
self.__server = server
self._SMTPChannel__server = server
self._SMTPChannel__conn = conn
self._SMTPChannel__addr = addr
self._SMTPChannel__line = []
self._SMTPChannel__state = self.COMMAND
self._SMTPChannel__greeting = 0
self._SMTPChannel__mailfrom = None
self._SMTPChannel__rcpttos = []
self._SMTPChannel__data = ''
self._SMTPChannel__fqdn = smtpd.socket.getfqdn()
self._SMTPChannel__peer = conn.getpeername()
self.__username = None
self.__password = None
self.__auth = 0
print >> smtpd.DEBUGSTREAM, 'Peer:', repr(self._SMTPChannel__peer)
self.push('220 %s ESMTP %s' % (self._SMTPChannel__fqdn, __version__))
self.set_terminator('\r\n')
def found_terminator(self):
if self._SMTPChannel__state != self.AUTH:
return smtpd.SMTPChannel.found_terminator(self)
line = smtpd.EMPTYSTRING.join(self._SMTPChannel__line)
print >> smtpd.DEBUGSTREAM, 'Data:', repr(line)
self._SMTPChannel__line = []
self.__auth_PLAIN(line)
def smtp_EHLO(self, arg):
if not arg:
self.push('501 Syntax: EHLO hostname')
return
if self._SMTPChannel__greeting:
self.push('503 Duplicate HELO/EHLO')
else:
self._SMTPChannel__greeting = arg
self.push('250-AUTH PLAIN')
self.push('250 AUTH=PLAIN')
def smtp_MAIL(self, arg):
if not self.__username:
self.push('503 Error: need AUTH command')
return
smtpd.SMTPChannel.smtp_MAIL(self, arg)
def smtp_RSET(self, arg):
if arg:
self.push('501 Syntax: RSET')
return
self.__username = None
self.__password = None
self.__server.disconnect()
smtpd.SMTPChannel.smtp_RSET(self, arg)
def smtp_QUIT(self, arg):
self.__server.disconnect()
smtpd.SMTPChannel.smtp_QUIT(self, arg)
def __auth_PLAIN(self, arg):
self._SMTPChannel__state = self.COMMAND
try:
decstring = base64.standard_b64decode(arg.strip())
except:
self.push('535 Error: authentication failed: bad protocol / cancel')
return
args = decstring.split('\0')
if len(args) != 3:
self.push('535 Error: authentication failed: bad protocol / cancel')
return
self.__username = args[1]
self.__password = args[2]
#print (' %s %s ' % ( self.__username, self.__password ))
status = self.__server.process_auth(self.__username, self.__password)
if not status:
self.push('235 Authentication successful')
else:
self.push(status)
self.__username = None
self.__password = None
def smtp_AUTH(self, arg):
if not arg:
self.push('501 Syntax: AUTH PLAIN xxxx')
return
else:
args = arg.split()
if args[0].upper() != 'PLAIN':
self.push('535 Error: authentication failed: no mechanism available')
return
if len(args) == 1:
self._SMTPChannel__state = self.AUTH
self.push('334 ')
return
return self.__auth_PLAIN(args[1])
class XMPPServer(ESMTPServer):
def process_auth(self, username, password):
self.__xmpp_domain = 'xmppserver'
self.__xmpp_server = '192.168.1.1'
self.__xmpp_port = 5222
jid=xmpp.protocol.JID(username)
if self.__xmpp_domain:
cl=xmpp.Client(self.__xmpp_domain, debug=[])
con=cl.connect(server=(self.__xmpp_server, self.__xmpp_port))
else:
cl=xmpp.Client(jid.getDomain(), debug=[])
con=cl.connect()
if not con:
cl.disconnect()
return '535 Error: authentication failed / internal server error'
print 'connected with',con
if jid.getNode():
auth=cl.auth(jid.getNode(), password, resource="Gateway") #jid.getResource())
else:
auth=cl.auth(username, password, resource="Gateway") #jid.getResource())
print auth
if not auth:
cl.disconnect()
return '535 Error: authentication failed'
self.__client = cl
def process_message(self, peer, mailfrom, rcpttos, data):
if not self.__client:
return '550 Error: internal server error'
for dest in rcpttos:
id=self.__client.send(xmpp.protocol.Message(dest, data))
def disconnect(self):
if self.__client:
self.__client.disconnect()
self.__client = None
if __name__ == '__main__':
myserver = XMPPServer(('0.0.0.0', 25), None)
try:
smtpd.asyncore.loop()
except KeyboardInterrupt:
pass
except:
raise



Recent comments
12 hours 10 min ago
13 hours 40 min ago
15 hours 17 min ago
16 hours 4 min ago
20 hours 50 min ago
1 day 1 min ago
1 day 15 min ago
1 day 27 min ago
1 day 37 min ago
1 day 41 min ago