Converting incoming messages into E-mail format, so that all bitmessages to a certain address are readable by E-mail clients.

This commit is contained in:
Chuck 2013-07-08 22:07:59 +07:00
parent d747394234
commit 04fe5134ef
3 changed files with 116 additions and 12 deletions

View File

@ -1,10 +1,14 @@
from cStringIO import StringIO
from collections import deque from collections import deque
import asyncore import asyncore
import hashlib
import shared import shared
import socket import socket
import ssl import ssl
import sys import sys
from email import parser, generator, utils
from addresses import * from addresses import *
import helper_inbox import helper_inbox
@ -61,10 +65,12 @@ class bitmessagePOP3Connection(asyncore.dispatcher):
for row in queryreturn: for row in queryreturn:
msgid, fromAddress, subject, size = row msgid, fromAddress, subject, size = row
subject = shared.fixPotentiallyInvalidUTF8Data(subject) subject = shared.fixPotentiallyInvalidUTF8Data(subject)
if subject.startswith("<Bitmessage Mail: ") and subject[-1] == '>': i = subject.find('<Bitmessage Mail: ')
subject = "<Bitmessage Mail: 00000000000000000000>" # Reserved, flags. if i >= 0:
flags = subject[-21:-1] tmp = subject[i:]
# TODO - checksum? i = tmp.find('>')
if i >= 0:
flags = tmp[i-21:i] # TODO - verify checksum?
self.messages.append({ self.messages.append({
'msgid': msgid, 'msgid': msgid,
@ -286,4 +292,89 @@ class bitmessagePOP3Server(asyncore.dispatcher):
sock = ssl.wrap_socket(sock, server_side=True, certfile=self.certfile, keyfile=self.keyfile, ssl_version=ssl.PROTOCOL_SSLv23) sock = ssl.wrap_socket(sock, server_side=True, certfile=self.certfile, keyfile=self.keyfile, ssl_version=ssl.PROTOCOL_SSLv23)
_ = bitmessagePOP3Connection(sock, peer_address, debug=self.debug) _ = bitmessagePOP3Connection(sock, peer_address, debug=self.debug)
@staticmethod
def reformatMessageForEmail(toAddress, fromAddress, body, subject):
message = parser.Parser().parsestr(body)
print(message)
subject_is_valid = False
i = subject.find('<Bitmessage Mail: ')
if i >= 0:
tmp = subject[i:]
i = tmp.find('>')
if i >= 0:
flags = tmp[i-21:i]
checksum = int(flags[-4:], 16)
# Checksum to makesure incoming message hasn't been tampered with
c = hashlib.sha256(body).digest()[:2]
c = (ord(checksum[0]) << 8) | ord(checksum[1])
# Valid Bitmessage subject line already
if c == checksum:
subject_is_valid = True
else:
with shared.printLock:
print 'Got E-Mail formatted message with incorrect checksum...'
body_is_valid = False
if 'Date' in message and 'From' in message:
body_is_valid = True
if not body_is_valid:
fromLabel = '{}@{}'.format(getBase58Capitaliation(fromAddress), fromAddress)
t = (fromAddress,)
with shared.sqlLock:
shared.sqlSubmitQueue.put(
'''SELECT label FROM addressbook WHERE address=?''')
shared.sqlSubmitQueue.put(t)
queryreturn = shared.sqlReturnQueue.get()
for row in queryreturn:
fromLabel = '{} <{}>'.format(row[0], fromLabel)
break
message['From'] = fromLabel
message['Date'] = utils.formatdate()
#if subject_is_valid and body_is_valid:
# return body, subject
if not subject_is_valid and 'Subject' not in message:
message['Subject'] = subject
toLabel = '{}@{}'.format(getBase58Capitaliation(toAddress), toAddress)
try:
toLabel = '{} <{}>'.format(shared.config.get(toAddress, 'label'), toLabel)
except:
pass
if "To" not in message:
message['To'] = toLabel
# Return-Path
returnPath = "{}@{}".format(getBase58Capitaliation(fromAddress), fromAddress)
message['Return-Path'] = returnPath
# X-Delivered-To
deliveredTo = "{}@{}".format(getBase58Capitaliation(toAddress), toAddress)
message['X-Delivered-To'] = deliveredTo
# X-Bitmessage-Receiving-Version
message["X-Bitmessage-Receiving-Version"] = shared.softwareVersion
fp = StringIO()
gen = generator.Generator(fp, mangle_from_=False, maxheaderlen=128)
gen.flatten(message)
message_as_text = fp.getvalue()
# Checksum to makesure incoming message hasn't been tampered with
# TODO - if subject_is_valid, then don't completely overwrite the subject, instead include all the data outside of <> too
checksum = hashlib.sha256(message_as_text).digest()[:2]
checksum = (ord(checksum[0]) << 8) | ord(checksum[1])
subject = "<Bitmessage Mail: 0000000000000000{:04x}>".format(checksum) # Reserved flags.
return message_as_text, subject

View File

@ -20,6 +20,8 @@ import helper_bitcoin
import helper_inbox import helper_inbox
import helper_sent import helper_sent
import tr import tr
from class_pop3Server import bitmessagePOP3Server
#from bitmessagemain import shared.lengthOfTimeToLeaveObjectsInInventory, shared.lengthOfTimeToHoldOnToAllPubkeys, shared.maximumAgeOfAnObjectThatIAmWillingToAccept, shared.maximumAgeOfObjectsThatIAdvertiseToOthers, shared.maximumAgeOfNodesThatIAdvertiseToOthers, shared.numberOfObjectsThatWeHaveYetToCheckAndSeeWhetherWeAlreadyHavePerPeer, shared.neededPubkeys #from bitmessagemain import shared.lengthOfTimeToLeaveObjectsInInventory, shared.lengthOfTimeToHoldOnToAllPubkeys, shared.maximumAgeOfAnObjectThatIAmWillingToAccept, shared.maximumAgeOfObjectsThatIAdvertiseToOthers, shared.maximumAgeOfNodesThatIAdvertiseToOthers, shared.numberOfObjectsThatWeHaveYetToCheckAndSeeWhetherWeAlreadyHavePerPeer, shared.neededPubkeys
# This thread is created either by the synSenderThread(for outgoing # This thread is created either by the synSenderThread(for outgoing
@ -997,7 +999,13 @@ class receiveDataThread(threading.Thread):
print 'Message ignored because address not in whitelist.' print 'Message ignored because address not in whitelist.'
blockMessage = True blockMessage = True
if not blockMessage: if not blockMessage:
try:
isEmailAddress = shared.config.getboolean(toAddress, 'foremail')
except:
isEmailAddress = False
print 'fromAddress:', fromAddress print 'fromAddress:', fromAddress
print 'toAddress is for E-mail:', isEmailAddress
print 'First 150 characters of message:', repr(message[:150]) print 'First 150 characters of message:', repr(message[:150])
toLabel = shared.config.get(toAddress, 'label') toLabel = shared.config.get(toAddress, 'label')
@ -1022,6 +1030,11 @@ class receiveDataThread(threading.Thread):
else: else:
body = 'Unknown encoding type.\n\n' + repr(message) body = 'Unknown encoding type.\n\n' + repr(message)
subject = '' subject = ''
if isEmailAddress:
# The above 'message/subject' formatting may give us weird values if messageEncodingType is bad
body, subject = bitmessagePOP3Server.reformatMessageForEmail(toAddress, fromAddress, body, subject)
if messageEncodingType != 0: if messageEncodingType != 0:
t = (self.inventoryHash, toAddress, fromAddress, subject, int( t = (self.inventoryHash, toAddress, fromAddress, subject, int(
time.time()), body, 'inbox', messageEncodingType, 0) time.time()), body, 'inbox', messageEncodingType, 0)

View File

@ -343,7 +343,7 @@ class bitmessageSMTPServer(smtpd.SMTPServer):
#print(type(address)) #print(type(address))
message = parser.Parser().parsestr(data) message = parser.Parser().parsestr(data)
message['X-Bitmessage-Version'] = shared.softwareVersion message['X-Bitmessage-Sending-Version'] = shared.softwareVersion
print(message) print(message)
fp = StringIO() fp = StringIO()