Change mail format to BMADDR@default. The word default can change. Also, get rid of the Bitmessage Mail tag in the subject line

This commit is contained in:
Chuck 2013-07-12 12:09:50 +07:00
parent 1e3cd7fc88
commit d8da925b8d
3 changed files with 112 additions and 179 deletions

View File

@ -199,26 +199,6 @@ def addBMIfNotPresent(address):
else: else:
return address return address
def getBase58Capitaliation(address):
if address[:3] == 'BM-':
address = address[3:]
i = []
for c in address:
i.append('1' if c.isupper() else '0')
return int(''.join(i), 2)
def applyBase58Capitalization(address, capitalization):
address = address.lower()
if address.startswith('bm-'):
address = address[3:]
n = []
for i, c in enumerate(address):
if (capitalization & (1 << (len(address)-i-1))) != 0:
n.append(c.upper())
else:
n.append(c)
return 'BM-' + ''.join(n)
def addressStream(address): def addressStream(address):
#returns the stream number of an address or False if there is a problem with the address. #returns the stream number of an address or False if there is a problem with the address.

View File

@ -55,7 +55,7 @@ class bitmessagePOP3Connection(asyncore.dispatcher):
v = (self.address,) v = (self.address,)
shared.sqlLock.acquire() shared.sqlLock.acquire()
# TODO LENGTH(message) needs to be the byte-length, not the character-length. # TODO LENGTH(message) needs to be the byte-length, not the character-length.
shared.sqlSubmitQueue.put('''SELECT msgid, fromaddress, subject, LENGTH(message) FROM inbox WHERE folder='inbox' AND toAddress=?''') shared.sqlSubmitQueue.put('''SELECT msgid, fromaddress, subject, message FROM inbox WHERE folder='inbox' AND toAddress=?''')
shared.sqlSubmitQueue.put(v) shared.sqlSubmitQueue.put(v)
queryreturn = shared.sqlReturnQueue.get() queryreturn = shared.sqlReturnQueue.get()
shared.sqlLock.release() shared.sqlLock.release()
@ -63,24 +63,25 @@ class bitmessagePOP3Connection(asyncore.dispatcher):
self.storage_size = 0 self.storage_size = 0
self.messages = [] self.messages = []
for row in queryreturn: for row in queryreturn:
msgid, fromAddress, subject, size = row msgid, fromAddress, subject, body = row
subject = shared.fixPotentiallyInvalidUTF8Data(subject) subject = shared.fixPotentiallyInvalidUTF8Data(subject)
i = subject.find('<Bitmessage Mail: ') body = shared.fixPotentiallyInvalidUTF8Data(body)
if i >= 0:
tmp = subject[i:] message = parser.Parser().parsestr(body)
i = tmp.find('>') if not ('Date' in message and 'From' in message and 'X-Bitmessage-Flags' in message):
if i >= 0: continue
flags = tmp[i-21:i] # TODO - verify checksum?
flags = message['X-Bitmessage-Flags'] # TODO - verify checksum?
self.messages.append({ self.messages.append({
'msgid': msgid, 'msgid' : msgid,
'fromAddress': fromAddress, 'fromAddress': fromAddress,
'subject': subject, 'subject' : subject,
'size': size, 'size' : len(body),
'flags' : flags,
}) })
self.storage_size += size self.storage_size += len(body)
def getMessageContent(self, msgid): def getMessageContent(self, msgid):
if self.address is None: if self.address is None:
@ -97,9 +98,9 @@ class bitmessagePOP3Connection(asyncore.dispatcher):
fromAddress, received, message, encodingtype = row fromAddress, received, message, encodingtype = row
message = shared.fixPotentiallyInvalidUTF8Data(message) message = shared.fixPotentiallyInvalidUTF8Data(message)
return { return {
'fromAddress': fromAddress, 'fromAddress' : fromAddress,
'received': received, 'received' : received,
'message': message, 'message' : message,
'encodingtype': encodingtype 'encodingtype': encodingtype
} }
@ -165,13 +166,10 @@ class bitmessagePOP3Connection(asyncore.dispatcher):
if self.loggedin: if self.loggedin:
raise Exception("Cannot login twice") raise Exception("Cannot login twice")
if '@' not in data: if '@' in data:
yield "-ERR access denied" data, _ = data.split('@', 1)
return
capitalization, address = data.split('@', 1)
self.address = applyBase58Capitalization(address, int(capitalization))
self.address = data
status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.address) status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.address)
if status != 'success': if status != 'success':
with shared.printLock: with shared.printLock:
@ -184,13 +182,6 @@ class bitmessagePOP3Connection(asyncore.dispatcher):
print 'Error: Address version number too high (or zero) in address: ' + self.address print 'Error: Address version number too high (or zero) in address: ' + self.address
raise Exception("Invalid Bitmessage address: {}".format(self.address)) raise Exception("Invalid Bitmessage address: {}".format(self.address))
username = '{}@{}'.format(getBase58Capitaliation(self.address), self.address)
# Must login with the full E-mail address and capitalization
if data != username:
yield "-ERR access denied"
return
# Each identity must be enabled independly by setting the smtppop3password for the identity # Each identity must be enabled independly by setting the smtppop3password for the identity
# If no password is set, then the identity is not available for SMTP/POP3 access. # If no password is set, then the identity is not available for SMTP/POP3 access.
try: try:
@ -295,6 +286,19 @@ 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 addMailingListNameToSubject(subject, mailingListName):
withoutre = subject = subject.strip()
re = ''
if subject[:3] == 'Re:' or subject[:3] == 'RE:':
re = subject[:3] + ' '
withoutre = subject[3:].strip()
a = '[' + mailingListName + ']'
if withoutre.startswith(a):
return subject
else:
return re + a + ' ' + subject
@staticmethod @staticmethod
def reformatMessageForReceipt(toAddress, fromAddress, body, subject, broadcast=False): def reformatMessageForReceipt(toAddress, fromAddress, body, subject, broadcast=False):
originalBody = body originalBody = body
@ -332,23 +336,10 @@ class bitmessagePOP3Server(asyncore.dispatcher):
print(message) print(message)
print '--------' print '--------'
i = subject.find('<Bitmessage Mail: ') flags = '0'
if i >= 0: if 'X-Bitmessage-Flags' in message:
tmp = subject[i:] flags = message['X-Bitmessage-Flags']
i = tmp.find('>') del message['X-Bitmessage-Flags']
if i >= 0:
flags = tmp[i-21:i]
checksum = int(flags[-4:], 16)
# Checksum to make sure incoming message hasn't been tampered with
c = hashlib.sha256(body).digest()[:2]
#c = (ord(checksum[0]) << 8) | ord(checksum[1])
print(c, checksum)
# Valid Bitmessage subject line already
if c != checksum:
with shared.printLock:
print 'Got E-Mail formatted message with incorrect checksum...'
mailingListName = None mailingListName = None
if broadcast: if broadcast:
@ -366,14 +357,16 @@ class bitmessagePOP3Server(asyncore.dispatcher):
if not body_is_valid: if not body_is_valid:
if broadcast: if broadcast:
if ostensiblyFrom is not None: if ostensiblyFrom is not None:
fromLabel = '{}@{}'.format(getBase58Capitaliation(ostensiblyFrom), ostensiblyFrom) fromLabel = '{} <{}@default>'.format(ostensiblyFrom, ostensiblyFrom)
# TODO - check address book? # TODO - check address book for label?
else: else:
fromLabel = '{}@{}'.format(getBase58Capitaliation(fromAddress), fromAddress) fromLabel = '{}@default'.format(fromAddress)
if mailingListName is not None: if mailingListName is not None:
fromLabel = '{} <{}>'.format(mailingListName, fromLabel) fromLabel = '{} <{}>'.format(mailingListName, fromLabel)
else: else:
fromLabel = '{}@{}'.format(getBase58Capitaliation(fromAddress), fromAddress) fromLabel = '{} <{}>'.format(fromAddress, fromLabel)
else:
fromLabel = '{}@default'.format(fromAddress)
with shared.sqlLock: with shared.sqlLock:
t = (fromAddress,) t = (fromAddress,)
@ -384,12 +377,12 @@ class bitmessagePOP3Server(asyncore.dispatcher):
for row in queryreturn: for row in queryreturn:
fromLabel = '{} <{}>'.format(row[0], fromLabel) fromLabel = '{} <{}>'.format(row[0], fromLabel)
break break
else:
fromLabel = '{} <{}>'.format(fromAddress, fromLabel)
message['From'] = fromLabel message['From'] = fromLabel
message['Date'] = utils.formatdate(localtime=False) message['Date'] = utils.formatdate(localtime=False)
message['X-Bitmessage-Subject'] = subject
if 'Subject' in message: if 'Subject' in message:
if mailingListName is not None: if mailingListName is not None:
s = message['Subject'] s = message['Subject']
@ -400,17 +393,18 @@ class bitmessagePOP3Server(asyncore.dispatcher):
if broadcast: if broadcast:
# The To: field on a broadcast is the mailing list, not you # The To: field on a broadcast is the mailing list, not you
toLabel = '{}@{}'.format(getBase58Capitaliation(fromAddress), fromAddress) toLabel = '{}@default'.format(fromAddress)
if mailingListName is not None: if mailingListName is not None:
toLabel = '{} <{}>'.format(mailingListName, toLabel) toLabel = '{} <{}>'.format(mailingListName, toLabel)
if 'To' in message: if 'To' in message:
del message['To'] del message['To']
message['To'] = toLabel message['To'] = toLabel
if 'Reply-To' not in message: if 'Reply-To' in message:
del message['Reply-To'] del message['Reply-To']
message['Reply-To'] = toLabel message['Reply-To'] = toLabel
elif 'To' not in message: else:
toLabel = '{}@{}'.format(getBase58Capitaliation(toAddress), toAddress) if 'To' not in message:
toLabel = '{}@default'.format(toAddress)
try: try:
toLabel = '{} <{}>'.format(shared.config.get(toAddress, 'label'), toLabel) toLabel = '{} <{}>'.format(shared.config.get(toAddress, 'label'), toLabel)
except: except:
@ -419,103 +413,72 @@ class bitmessagePOP3Server(asyncore.dispatcher):
message['To'] = toLabel message['To'] = toLabel
# Return-Path # Return-Path
returnPath = "{}@{}".format(getBase58Capitaliation(fromAddress), fromAddress) returnPath = "{}@default".format(fromAddress)
message['Return-Path'] = returnPath message['Return-Path'] = returnPath
# X-Delivered-To # X-Delivered-To
deliveredTo = "{}@{}".format(getBase58Capitaliation(toAddress), toAddress) deliveredTo = "{}@default".format(toAddress)
message['X-Delivered-To'] = deliveredTo message['X-Delivered-To'] = deliveredTo
# X-Bitmessage-Receiving-Version # X-Bitmessage-Receiving-Version
message["X-Bitmessage-Receiving-Version"] = shared.softwareVersion message["X-Bitmessage-Receiving-Version"] = shared.softwareVersion
# Others...
message['X-Bitmessage-Subject'] = subject
message['X-Bitmessage-Flags'] = flags
fp = StringIO() fp = StringIO()
gen = generator.Generator(fp, mangle_from_=False, maxheaderlen=128) gen = generator.Generator(fp, mangle_from_=False, maxheaderlen=128)
gen.flatten(message) gen.flatten(message)
message_as_text = fp.getvalue() 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 return message_as_text, subject
@staticmethod
def addMailingListNameToSubject(subject, mailingListName):
withoutre = subject = subject.strip()
re = ''
if subject[:3] == 'Re:' or subject[:3] == 'RE:':
re = subject[:3] + ' '
withoutre = subject[3:].strip()
a = '[' + mailingListName + ']'
if withoutre.startswith(a):
return subject
else:
return re + a + ' ' + subject
@staticmethod @staticmethod
def reformatMessageForMailingList(toAddress, fromAddress, body, subject, mailingListName): def reformatMessageForMailingList(toAddress, fromAddress, body, subject, mailingListName):
message = parser.Parser().parsestr(body) message = parser.Parser().parsestr(body)
with shared.printLock: with shared.printLock:
print(message) print(message)
subject_is_valid = False flags = '0'
if 'X-Bitmessage-Flags' in message:
flags = message['X-Bitmessage-Flags']
del message['X-Bitmessage-Flags']
i = subject.find('<Bitmessage Mail: ') # The mailing list code will override some headers, including Date and From
if i >= 0: fromLabel = '{}@default'.format(fromAddress)
tmp = subject[i:]
i = tmp.find('>')
if i >= 0:
flags = tmp[i-21:i]
checksum = int(flags[-4:], 16)
# Checksum to make sure 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...'
# The mailing list code will override some headers, including Date and From, so
# that the trust can be moved from the original sender to the mailing list owner.
fromLabel = '{}@{}'.format(getBase58Capitaliation(fromAddress), fromAddress)
if 'From' in message: if 'From' in message:
originalFrom = message['From'] originalFrom = message['From']
message['X-Original-From'] = originalFrom message['X-Original-From'] = originalFrom
i = originalFrom.find('<' + fromLabel + '>') i = originalFrom.find('<' + fromAddress + '@')
if i >= 0: if i >= 0:
fromLabel = '{} <{}>'.format(originalFrom[:i].strip(), fromLabel) fromLabel = '{} <{}>'.format(originalFrom[:i].strip(), fromLabel)
else:
fromLabel = '{} <{}>'.format(fromAddress, fromLabel)
del message['From']
message['From'] = fromLabel message['From'] = fromLabel
message['Date'] = utils.formatdate()
if 'Date' in message:
del message['Date']
message['Date'] = utils.formatdate(localtime=False)
message['X-Bitmessage-Subject'] = subject message['X-Bitmessage-Subject'] = subject
if 'Subject' not in message: if 'Subject' not in message:
if not subject_is_valid:
message['Subject'] = bitmessagePOP3Server.addMailingListNameToSubject(subject, mailingListName) message['Subject'] = bitmessagePOP3Server.addMailingListNameToSubject(subject, mailingListName)
else: else:
# TODO - strip <Bitmessage Mail: ...> from bitmessage subject? s = message['Subject']
message['Subject'] = bitmessagePOP3Server.addMailingListNameToSubject('', mailingListName) del message['Subject']
else: message['Subject'] = bitmessagePOP3Server.addMailingListNameToSubject(s, mailingListName)
message['Subject'] = bitmessagePOP3Server.addMailingListNameToSubject(message['Subject'], mailingListName)
toLabel = '{}@{}'.format(getBase58Capitaliation(toAddress), toAddress)
try:
toLabel = '{} <{}>'.format(shared.config.get(toAddress, 'label'), toLabel)
except:
pass
toLabel = '"{}" <{}@default>'.format(mailingListName, toAddress)
if 'To' in message: if 'To' in message:
message['X-Original-To'] = message['To'] message['X-Original-To'] = message['To']
del message['To']
message['To'] = toLabel message['To'] = toLabel
# X-Bitmessage-MailingList-Name # X-Bitmessage-MailingList-Name
@ -528,17 +491,12 @@ class bitmessagePOP3Server(asyncore.dispatcher):
# X-Bitmessage-MailingList-Version # X-Bitmessage-MailingList-Version
message["X-Bitmessage-MailingList-Version"] = shared.softwareVersion message["X-Bitmessage-MailingList-Version"] = shared.softwareVersion
message["X-Bitmessage-Flags"] = flags
fp = StringIO() fp = StringIO()
gen = generator.Generator(fp, mangle_from_=False, maxheaderlen=128) gen = generator.Generator(fp, mangle_from_=False, maxheaderlen=128)
gen.flatten(message) gen.flatten(message)
message_as_text = fp.getvalue() 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 = bitmessagePOP3Server.addMailingListNameToSubject("<Bitmessage Mail: 0000000000000000{:04x}>".format(checksum), mailingListAddress)
return message_as_text, subject return message_as_text, subject

View File

@ -172,13 +172,12 @@ class bitmessageSMTPChannel(asynchat.async_chat):
self.invalid_command('501 authorization not understood') self.invalid_command('501 authorization not understood')
return return
if '@' not in username: if '@' in username:
self.invalid_command('530 Access denied.') username, _ = username.split('@', 1)
return
capitalization, address = username.split('@', 1)
self.address = applyBase58Capitalization(address, int(capitalization))
self.address = username
with shared.printLock:
print 'Login request from {}'.format(self.address)
status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.address) status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.address)
if status != 'success': if status != 'success':
with shared.printLock: with shared.printLock:
@ -191,13 +190,6 @@ class bitmessageSMTPChannel(asynchat.async_chat):
print 'Error: Address version number too high (or zero) in address: ' + self.address print 'Error: Address version number too high (or zero) in address: ' + self.address
raise Exception("Invalid Bitmessage address: {}".format(self.address)) raise Exception("Invalid Bitmessage address: {}".format(self.address))
self.fullUsername = '{}@{}'.format(getBase58Capitaliation(self.address), address)
# Must match full email address with capitalization
if username != self.fullUsername:
self.invalid_command('530 Access denied.')
return
# Each identity must be enabled independly by setting the smtppop3password for the identity # Each identity must be enabled independly by setting the smtppop3password for the identity
# If no password is set, then the identity is not available for SMTP/POP3 access. # If no password is set, then the identity is not available for SMTP/POP3 access.
try: try:
@ -242,7 +234,7 @@ class bitmessageSMTPChannel(asynchat.async_chat):
print >> smtpd.DEBUGSTREAM, '===> MAIL', arg print >> smtpd.DEBUGSTREAM, '===> MAIL', arg
address = self.__getaddr('FROM:', arg) if arg else None address = self.__getaddr('FROM:', arg) if arg else None
if not address: if not address or '@' not in address:
self.invalid_command('501 Syntax: MAIL FROM: <address>') self.invalid_command('501 Syntax: MAIL FROM: <address>')
return return
@ -254,7 +246,8 @@ class bitmessageSMTPChannel(asynchat.async_chat):
self.invalid_command('503 Not authenticated.') self.invalid_command('503 Not authenticated.')
return return
if address != self.fullUsername: localPart, _ = address.split('@', 1)
if self.address != localPart:
self.invalid_command('530 Access denied: address must be the same as the authorized account') self.invalid_command('530 Access denied: address must be the same as the authorized account')
return return
@ -278,12 +271,15 @@ class bitmessageSMTPChannel(asynchat.async_chat):
self.invalid_command('501 Syntax: RCPT TO: <user@address>') self.invalid_command('501 Syntax: RCPT TO: <user@address>')
return return
try: try:
capitalization, address = address.split('@', 1) localPart, dom = address.split('@', 1)
except ValueError: except ValueError:
self.invalid_command('501 Syntax: RCPT TO: <user@address>') self.invalid_command('501 Syntax: RCPT TO: <user@address>')
return return
realAddress = applyBase58Capitalization(address, int(capitalization)) status, addressVersionNumber, streamNumber, fromRipe = decodeAddress(localPart)
self.__rcpttos.append('{}@{}'.format(getBase58Capitaliation(realAddress), realAddress)) if status != 'success':
self.invalid_command('501 Bitmessage address is incorrect: {}'.format(status))
return
self.__rcpttos.append(address)
with shared.printLock: with shared.printLock:
print >> smtpd.DEBUGSTREAM, 'recips:', self.__rcpttos print >> smtpd.DEBUGSTREAM, 'recips:', self.__rcpttos
self.push('250 Ok') self.push('250 Ok')
@ -341,17 +337,12 @@ class bitmessageSMTPServer(smtpd.SMTPServer):
@staticmethod @staticmethod
def stripMessageHeaders(message): def stripMessageHeaders(message):
# Convert Date header into GMT # Always convert Date header into GMT
if 'Date' in message: if 'Date' in message:
oldDate = message['Date'] oldDate = message['Date']
del message['Date'] del message['Date']
message['Date'] = utils.formatdate(utils.mktime_tz(utils.parsedate_tz(oldDate)), localtime=False) message['Date'] = utils.formatdate(utils.mktime_tz(utils.parsedate_tz(oldDate)), localtime=False)
with shared.printLock:
print 'old date --', oldDate
print 'new date --', message['Date']
try: try:
if not shared.config.getboolean('bitmessagesettings', 'stripmessageheadersenable'): if not shared.config.getboolean('bitmessagesettings', 'stripmessageheadersenable'):
return return
@ -368,22 +359,24 @@ class bitmessageSMTPServer(smtpd.SMTPServer):
if h in message: if h in message:
del message[h] del message[h]
def process_message(self, peer, address, rcpttos, data): def process_message(self, peer, fromAddress, rcpttos, data):
#print("Peer", peer) #print("Peer", peer)
#print("Mail From", address) #print("Mail From", fromAddress)
#print("Rcpt To", rcpttos) #print("Rcpt To", rcpttos)
#print("Data") #print("Data")
#print(data) #print(data)
#print('--------') #print('--------')
#print(type(address)) #print(type(fromAddress))
message = parser.Parser().parsestr(data) message = parser.Parser().parsestr(data)
message['X-Bitmessage-Sending-Version'] = shared.softwareVersion message['X-Bitmessage-Sending-Version'] = shared.softwareVersion
message['X-Bitmessage-Flags'] = '0'
bitmessageSMTPServer.stripMessageHeaders(message) bitmessageSMTPServer.stripMessageHeaders(message)
fp = StringIO() fp = StringIO()
gen = generator.Generator(fp, mangle_from_=False, maxheaderlen=128) gen = generator.Generator(fp, mangle_from_=False, maxheaderlen=128)
gen.flatten(message) gen.flatten(message)
message_as_text = fp.getvalue() message_as_text = fp.getvalue()
with shared.printLock: with shared.printLock:
print(message_as_text) print(message_as_text)
@ -392,7 +385,6 @@ class bitmessageSMTPServer(smtpd.SMTPServer):
checksum = (ord(checksum[0]) << 8) | ord(checksum[1]) checksum = (ord(checksum[0]) << 8) | ord(checksum[1])
# Determine the fromAddress and make sure it's an owned identity # Determine the fromAddress and make sure it's an owned identity
fromAddress = address
if not (fromAddress.startswith('BM-') and '.' not in fromAddress): if not (fromAddress.startswith('BM-') and '.' not in fromAddress):
raise Exception("From Address must be a Bitmessage address.") raise Exception("From Address must be a Bitmessage address.")
else: else:
@ -421,7 +413,7 @@ class bitmessageSMTPServer(smtpd.SMTPServer):
raise Exception("The fromAddress is disabled: {}".format(fromAddress)) raise Exception("The fromAddress is disabled: {}".format(fromAddress))
for recipient in rcpttos: for recipient in rcpttos:
_, toAddress = recipient.split('@', 1) toAddress, _ = recipient.split('@', 1)
if not (toAddress.startswith('BM-') and '.' not in toAddress): if not (toAddress.startswith('BM-') and '.' not in toAddress):
# TODO - deliver message to another SMTP server.. # TODO - deliver message to another SMTP server..
# I think this feature would urge adoption: the ability to use the same bitmessage address # I think this feature would urge adoption: the ability to use the same bitmessage address
@ -461,7 +453,10 @@ class bitmessageSMTPServer(smtpd.SMTPServer):
# The subject is specially formatted to identify it from non-E-mail messages. # The subject is specially formatted to identify it from non-E-mail messages.
# TODO - The bitfield will be used to convey things like external attachments, etc. # TODO - The bitfield will be used to convey things like external attachments, etc.
# Last 2 bytes are two bytes of the sha256 checksum of message # Last 2 bytes are two bytes of the sha256 checksum of message
subject = "<Bitmessage Mail: 0000000000000000{:04x}>".format(checksum) # Reserved flags. if 'Subject' in message:
subject = message['Subject']
else:
subject = ''
ackdata = OpenSSL.rand(32) ackdata = OpenSSL.rand(32)
t = ('', toAddress, toRipe, fromAddress, subject, message_as_text, ackdata, int(time.time()), 'msgqueued', 1, 1, 'sent', 2) t = ('', toAddress, toRipe, fromAddress, subject, message_as_text, ackdata, int(time.time()), 'msgqueued', 1, 1, 'sent', 2)