diff --git a/bminterface.py b/bminterface.py
index 423af94..1560e7c 100644
--- a/bminterface.py
+++ b/bminterface.py
@@ -1,11 +1,16 @@
-import ConfigParser
-import xmlrpclib
-import json
+from six.moves import configparser
+from six.moves import xmlrpc_client
import datetime
import time
import email.utils
import os
import logging
+from codecs import encode, decode
+
+try:
+ SafeConfigParser = configparser.SafeConfigParser
+except AttributeError:
+ SafeConfigParser = configparser.ConfigParser
purgeList = []
allMessages = []
@@ -17,7 +22,7 @@ def _getKeyLocation(): #make this not suck later
def _getConfig(keys):
return apiData()
#TODO make this work, so the above can be removed
- config = ConfigParser.SafeConfigParser()
+ config = SafeConfigParser()
config.read(keys)
try:
api_port = config.getint('bitmessagesettings', 'apiport')
@@ -30,7 +35,7 @@ def _getConfig(keys):
return "http://"+api_uname+":"+api_passwd+"@"+api_iface+":"+str(api_port)+"/"
def _makeApi(keys):
- return xmlrpclib.ServerProxy(_getConfig(keys))
+ return xmlrpc_client.ServerProxy(_getConfig(keys))
def _sendMessage(toAddress, fromAddress, subject, body):
api = _makeApi(_getKeyLocation())
@@ -73,8 +78,8 @@ def registerAddress(address):
def send(toAddress, fromAddress, subject, body):
toAddress = _stripAddress(toAddress)
fromAddress = _stripAddress(fromAddress)
- subject = subject.encode('base64')
- body = body.encode('base64')
+ subject = encode(subject.encode("utf-8", "replace"), 'base64').decode("utf-8", "replace")
+ body = encode(body.encode("utf-8", "replace"), 'base64').decode("utf-8", "replace")
if toAddress == 'broadcast':
return _sendBroadcast(fromAddress, subject, body)
else:
@@ -85,12 +90,13 @@ def _getAll():
global currentAddress
if not allMessages:
api = _makeApi(_getKeyLocation())
- allMessages = json.loads(api.getAllInboxMessages())
+ allMessages = api.getAllInboxMessages()
logging.debug("current address is %s" % currentAddress)
if currentAddress is not None:
ret = []
+ cur_addr = currentAddress.decode("utf-8", "replace")
for msg in allMessages['inboxMessages']:
- if msg['toAddress'] == currentAddress:
+ if msg['toAddress'] == cur_addr:
ret.append(msg)
return dict(inboxMessages=ret)
return allMessages
@@ -105,8 +111,8 @@ def get(msgID):
#if 'Broadcast' in toAddress:
# toAddress = fromAddress
- subject = inboxMessages['inboxMessages'][msgID]['subject'].decode('base64')
- body = inboxMessages['inboxMessages'][msgID]['message'].decode('base64')
+ subject = decode(inboxMessages['inboxMessages'][msgID]['subject'].encode("utf-8", "replace"), 'base64')
+ body = decode(inboxMessages['inboxMessages'][msgID]['message'].encode("utf-8", "replace"), 'base64')
return dateTime, toAddress, fromAddress, subject, body
def listMsgs():
@@ -135,7 +141,7 @@ def _deleteMessage(msgRef):
def getUIDLforAll():
api = _makeApi(_getKeyLocation())
- inboxMessages = json.loads(api.getAllInboxMessages())
+ inboxMessages = _getAll()
refdata = []
for msgID in range(len(inboxMessages['inboxMessages'])):
msgRef = inboxMessages['inboxMessages'][msgID]['msgid'] #gets the message Ref via the message index number
@@ -144,7 +150,7 @@ def getUIDLforAll():
def getUIDLforSingle(msgID):
api = _makeApi(_getKeyLocation())
- inboxMessages = json.loads(api.getAllInboxMessages())
+ inboxMessages = _getAll()
msgRef = inboxMessages['inboxMessages'][msgID]['msgid'] #gets the message Ref via the message index number
return [str(msgRef)]
@@ -170,7 +176,7 @@ def lookupAppdataFolder(): #gets the appropriate folders for the .dat files depe
def apiData():
global keysPath
- config = ConfigParser.SafeConfigParser()
+ config = SafeConfigParser()
keysPath = 'keys.dat'
config.read(keysPath) #First try to load the config file (the keys.dat file) from the program directory
@@ -181,30 +187,30 @@ def apiData():
#Could not load the keys.dat file in the program directory. Perhaps it is in the appdata directory.
appDataFolder = lookupAppdataFolder()
keysPath = appDataFolder + 'keys.dat'
- config = ConfigParser.SafeConfigParser()
+ config = SafeConfigParser()
config.read(keysPath)
try:
config.get('bitmessagesettings','settingsversion')
except:
#keys.dat was not there either, something is wrong.
- print ' '
- print '******************************************************************'
- print 'There was a problem trying to access the Bitmessage keys.dat file.'
- print 'Make sure that daemon is in the same directory as Bitmessage.'
- print '******************************************************************'
- print ' '
- print config
- print ' '
+ print(' ')
+ print('******************************************************************')
+ print('There was a problem trying to access the Bitmessage keys.dat file.')
+ print('Make sure that daemon is in the same directory as Bitmessage.')
+ print('******************************************************************')
+ print(' ')
+ print(config)
+ print(' ')
try:
apiConfigured = config.getboolean('bitmessagesettings','apienabled') #Look for 'apienabled'
apiEnabled = apiConfigured
except:
apiConfigured = False #If not found, set to false since it still needs to be configured
- print "You need to edit your keys.dat file and enable bitmessage's API"
- print "See for more details: https://bitmessage.org/wiki/API"
- print "Will now crash..."
+ print("You need to edit your keys.dat file and enable bitmessage's API")
+ print("See for more details: https://bitmessage.org/wiki/API")
+ print("Will now crash...")
raise
#if (apiConfigured == False):#If the apienabled == false or is not present in the keys.dat file, notify the user and set it up
diff --git a/incoming.py b/incoming.py
index 7a8987a..045a276 100644
--- a/incoming.py
+++ b/incoming.py
@@ -11,7 +11,7 @@
class ChatterboxConnection(object):
- END = "\r\n"
+ END = b"\r\n"
def __init__(self, conn):
self.conn = conn
def __getattr__(self, name):
@@ -33,23 +33,23 @@ def recvall(self, END=END):
data[-2] = pair[:pair.index(END)]
data.pop()
break
- return "".join(data)
+ return b"".join(data)
def handleUser(data):
d = data.split()
logging.debug("data:%s" % d)
username = d[-1]
- if username[:3] == 'BM-':
+ if username[:3] == b'BM-':
logging.debug("Only showing messages for %s" % username)
bminterface.registerAddress(username)
else:
logging.debug("Showing all messages in the inbox")
bminterface.registerAddress(None)
- return "+OK user accepted"
+ return b"+OK user accepted"
def handlePass(data):
- return "+OK pass accepted"
+ return b"+OK pass accepted"
def _getMsgSizes():
msgCount = bminterface.listMsgs()
@@ -66,7 +66,7 @@ def handleStat(data):
msgSizeTotal = 0
for msgSize in msgSizes:
msgSizeTotal += msgSize
- returnData = '+OK %i %i' % (msgCount, msgSizeTotal)
+ returnData = b'+OK %i %i' % (msgCount, msgSizeTotal)
logging.debug("Answering STAT: %i %i" % (msgCount, msgSizeTotal))
return returnData
@@ -79,26 +79,26 @@ def handleList(data):
# means the server wants a single message response
i = int(msgId) - 1
if i >= len(msgSizes):
- return "-ERR no such message"
+ return b"-ERR no such message"
else:
msgSize = msgSizes[i]
- return "+OK %s %s" % (msgId, msgSize)
+ return b"+OK %i %i" % (msgId, msgSize)
msgCount = 0
- returnDataPart2 = ''
+ returnDataPart2 = b''
msgSizeTotal = 0
for msgSize in msgSizes:
msgSizeTotal += msgSize
msgCount += 1
- returnDataPart2 += '%i %i\r\n' % (msgCount, msgSize)
- returnDataPart2 += '.'
- returnDataPart1 = '+OK %i messages (%i octets)\r\n' % (msgCount, msgSizeTotal)
+ returnDataPart2 += b'%i %i\r\n' % (msgCount, msgSize)
+ returnDataPart2 += b'.'
+ returnDataPart1 = b'+OK %i messages (%i octets)\r\n' % (msgCount, msgSizeTotal)
returnData = returnDataPart1 + returnDataPart2
logging.debug("Answering LIST: %i %i" % (msgCount, msgSizeTotal))
logging.debug(returnData)
return returnData
def handleTop(data):
- msg = 'test'
+ msg = b'test'
logging.debug(data.split())
cmd, msgID, lines = data.split()
msgID = int(msgID)-1
@@ -107,34 +107,37 @@ def handleTop(data):
dateTime, toAddress, fromAddress, subject, body = bminterface.get(msgID)
logging.debug(subject)
msg = makeEmail(dateTime, toAddress, fromAddress, subject, body)
- top, bot = msg.split("\n\n", 1)
- #text = top + "\r\n\r\n" + "\r\n".join(bot[:lines])
- return "+OK top of message follows\r\n%s\r\n." % top
+ top, bot = msg.split(b"\n\n", 1)
+ #text = top + b"\r\n\r\n" + b"\r\n".join(bot[:lines])
+ return b"+OK top of message follows\r\n%s\r\n." % top
def handleRetr(data):
logging.debug(data.split())
msgID = int(data.split()[1])-1
+ msgCount = bminterface.listMsgs()
+ if msgID >= msgCount:
+ return b"-ERR no such message"
dateTime, toAddress, fromAddress, subject, body = bminterface.get(msgID)
msg = makeEmail(dateTime, toAddress, fromAddress, subject, body)
- return "+OK %i octets\r\n%s\r\n." % (len(msg), msg)
+ return b"+OK %i octets\r\n%b\r\n." % (len(msg), msg.encode("utf-8", "replace"))
def handleDele(data):
msgID = int(data.split()[1])-1
bminterface.markForDelete(msgID)
- return "+OK I'll try..."
+ return b"+OK I'll try..."
def handleNoop(data):
- return "+OK"
+ return b"+OK"
def handleQuit(data):
bminterface.cleanup()
- return "+OK just pretend I'm gone"
+ return b"+OK just pretend I'm gone"
def handleCapa(data):
- returnData = "+OK List of capabilities follows\r\n"
+ returnData = b"+OK List of capabilities follows\r\n"
for k in dispatch:
- returnData += "%s\r\n" % k
- returnData += "."
+ returnData += b"%b\r\n" % k.encode("utf-8", "replace")
+ returnData += b"."
return returnData
def handleUIDL(data):
@@ -143,14 +146,14 @@ def handleUIDL(data):
if len(data) == 1:
refdata = bminterface.getUIDLforAll()
logging.debug(refdata)
- returnData = '+OK\r\n'
+ returnData = b'+OK\r\n'
for msgID, d in enumerate(refdata):
- returnData += "%s %s\r\n" % (msgID+1, d)
- returnData += '.'
+ returnData += b"%i %b\r\n" % (msgID+1, d.encode("utf-8", "replace"))
+ returnData += b'.'
else:
refdata = bminterface.getUIDLforSingle(int(data[1])-1)
logging.debug(refdata)
- returnData = '+OK ' + data[0] + str(refdata[0])
+ returnData = b'+OK ' + data[0] + refdata[0]
return returnData
def makeEmail(dateTime, toAddress, fromAddress, subject, body):
@@ -198,16 +201,16 @@ def makeEmail(dateTime, toAddress, fromAddress, subject, body):
def parseBody(body):
returnData = []
- text = ''
- searchString = '
]*'
+ text = b''
+ searchString = b'
]*'
attachment = re.search(searchString, body)
while attachment:
imageCode = body[attachment.start():attachment.end()]
- imageDataRange = re.search('src=[\"\'][^\"\']*[\"\']', imageCode)
+ imageDataRange = re.search(b'src=[\"\'][^\"\']*[\"\']', imageCode)
imageData=''
if imageDataRange:
try:
- imageData = imageCode[imageDataRange.start()+5:imageDataRange.end()-1].lstrip('data:')
+ imageData = imageCode[imageDataRange.start()+5:imageDataRange.end()-1].lstrip(b'data:')
except:
pass
if imageData:
@@ -257,15 +260,15 @@ def incomingServer_main(host, port, run_event):
sock = None
try:
conn = ChatterboxConnection(conn)
- conn.sendall("+OK server ready")
+ conn.sendall(b"+OK server ready")
while run_event.is_set():
data = conn.recvall()
logging.debug("Answering %s" % data)
- command = data.split(None, 1)[0]
+ command = data.split(None, 1)[0].decode("utf-8", "replace")
try:
cmd = dispatch[command]
except KeyError:
- conn.sendall("-ERR unknown command")
+ conn.sendall(b"-ERR unknown command")
else:
conn.sendall(cmd(data))
if cmd is handleQuit:
@@ -275,7 +278,7 @@ def incomingServer_main(host, port, run_event):
except (SystemExit, KeyboardInterrupt):
pass
- except Exception, ex:
+ except Exception as ex:
raise
finally:
if sock is not None:
diff --git a/outgoing.py b/outgoing.py
index c2e787d..8b24cb6 100644
--- a/outgoing.py
+++ b/outgoing.py
@@ -5,14 +5,14 @@
import logging
class outgoingServer(SMTPServer):
- def process_message(self, peer, mailfrom, rcpttos, data):
+ def process_message(self, peer, mailfrom, rcpttos, data, mail_options=[], rcpt_options=[]):
parser = email.parser.FeedParser()
- parser.feed(data)
+ parser.feed(data.decode("utf-8", "replace"))
msg = parser.close()
toAddress = msg['To']
fromAddress = msg['From']
- subject = u' '.join(unicode(t[0], t[1] or 'UTF-8') for t in email.header.decode_header(msg['Subject'])).encode('UTF-8')
+ subject = ' '.join(t[0] for t in email.header.decode_header(msg['Subject']))
body = self._bmformat(msg)
#Make sure we don't send an actually blank subject or body--this can cause problems.
@@ -49,7 +49,7 @@ def _recurseParse(self, msg):
if 'text/plain' in item['Content-Type']:
text += item.get_payload()
elif 'image' in item['Content-Type']:
- [filetype, name] = item['Content-Type'].rstrip().split('\n')
+ filetype, name = item['Content-Type'].rstrip().split(' ')
name = name.replace('name', 'alt')
imageraw = item.get_payload().rstrip().split('\n')
imagedata = ''