def check_bmoutbox(intcond): global interrupted ## get all messages #all_messages = json.loads(api['conn'].getAllInboxMessages())['inboxMessages'] logging.info("Entering BM outbox checker loop") intcond.acquire() while not interrupted: all_messages = get_outbox() logging.info("Trashing old outbox messages") ## if no messages if not all_messages: try: intcond.wait(BMConfig().get("bmgateway", "bmgateway", "outbox_process_interval")) except KeyboardInterrupt: break continue ## loop through messages to find unread for a_message in all_messages: if a_message['status'] == 'ackreceived': userdata = lib.user.GWUser(bm = a_message['toAddress']) if userdata: userdata.setlastackreceived(a_message['lastActionTime']) BMMessage.deleteStatic(a_message['msgid'], folder = "outbox") logging.info("Vacuuming DB") result = BMAPI().conn().deleteAndVacuum() intcond.wait(BMConfig().get("bmgateway", "bmgateway", "outbox_process_interval")) intcond.release() logging.info("Leaving BM outbox checker loop")
def check_bmoutbox(intcond): global interrupted ## get all messages #all_messages = json.loads(api['conn'].getAllInboxMessages())['inboxMessages'] logging.info("Entering BM outbox checker loop") intcond.acquire() while not interrupted: all_messages = get_outbox() logging.info("Trashing old outbox messages") ## if no messages if not all_messages: try: intcond.wait(BMConfig().get("bmgateway", "bmgateway", "outbox_process_interval")) except KeyboardInterrupt: break continue ## loop through messages to find unread for a_message in all_messages: if a_message['status'] == 'ackreceived': BMMessage.deleteStatic(a_message['msgid'], folder = "outbox") logging.info("Vacuuming DB") result = BMAPI().conn().deleteAndVacuum() intcond.wait(BMConfig().get("bmgateway", "bmgateway", "outbox_process_interval")) intcond.release() logging.info("Leaving BM outbox checker loop")
def check_bminbox(intcond): global interrupted ## get all messages #all_messages = json.loads(api['conn'].getAllInboxMessages())['inboxMessages'] logging.info("Entering BM inbox checker loop") intcond.acquire() while not interrupted: all_messages = get_inbox() ## if no messages if not all_messages: try: intcond.wait(BMConfig().get("bmgateway", "bmgateway", "process_interval")) except KeyboardInterrupt: break continue ## loop through messages to find unread for a_message in all_messages: ## if already read, delete and break if a_message['read'] == 1: BMMessage.deleteStatic(a_message['msgid']) continue ## check if already processed, maybe from another instance if lib.bminbox.check_message_processed(a_message['msgid']): logging.info('Message %s has already been processed deleting...', a_message['msgid']) # BMMessage.deleteStatic(a_message['msgid']) # continue ## if the message is unread, load it by ID to trigger the read flag message = json.loads(BMAPI().conn().getInboxMessageByID(a_message['msgid'], False))['inboxMessage'][0] ## if a blank message was returned if not message: logging.error('API returned blank message when requesting a message by msgID') delete_bitmessage_inbox(bm_id) BMMessage.deleteStatic(a_message['msgid']) continue ## find message ID bm_id = message['msgid'] ## check if receive address is a DEregistration request if field_in_list(message, BMAPI().address_list, 'toAddress', 'deregistration_address_label'): ## check if address is registered userdata = lib.user.GWUser(bm = message['fromAddress']) ## if the sender is actually registered and wants to deregister if userdata.check(): ## process deregistration logging.info('Processed deregistration request for user ' + userdata.email) delete_address(message['fromAddress']) ## send deregistration confirmation email SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "deregistration_address_label")), recipient = message['fromAddress'], template = "deregistration-confirmed", addmaps = { 'email': userdata.email }) ## bogus deregistration request else: logging.warn('Purged malicious deregistration bitmessage from ' + message['fromAddress']) elif field_in_list(message, BMAPI().address_list, 'toAddress', 'bug_report_address_label'): userdata = lib.user.GwUser(bm = message['fromAddress']) # if not, create a fake one # relay to ticket ## check if receive address is a registration request elif field_in_list(message, BMAPI().address_list, 'toAddress', 'registration_address_label'): userdata = lib.user.GWUser(bm = message['fromAddress']) if userdata.check(): # status, config, etc command = base64.b64decode(message['subject']).lower() if command == "config": logging.info('Config request from %s', message['fromAddress']) body = base64.b64decode(message['message']) data = {} for line in body.splitlines(): line = re.sub("#.*", "", line) option = re.search("(\S+)\s*:\s*(\S+)", line) if option is None: continue if option.group(1).lower() == "pgp": data['pgp'] = lib.user.GWUserData.pgp(option.group(2)) elif option.group(1).lower() == "attachments": data['attachments'] = lib.user.GWUserData.zero_one(option.group(2)) #elif option.group(1).lower() == "flags": #data['flags'] = lib.user.GWUserData.numeric(option.group(2)) elif option.group(1).lower() == "archive": data['archive'] = lib.user.GWUserData.zero_one(option.group(2)) elif option.group(1).lower() == "masterpubkey_btc": data['masterpubkey_btc'] = lib.user.GWUserData.public_seed(option.group(2)) # reset offset unless set explicitly if data['masterpubkey_btc'] is not None and not 'offset_btc' in data: data['offset_btc'] = "0" elif option.group(1).lower() == "offset_btc": data['offset_btc'] = lib.user.GWUserData.numeric(option.group(2)) elif option.group(1).lower() == "feeamount": data['feeamount'] = lib.user.GWUserData.numeric(option.group(2), 8) elif option.group(1).lower() == "feecurrency": data['feecurrency'] = lib.user.GWUserData.currency(option.group(2)) else: pass if userdata.update(data): SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "configchange", addmaps = { }) else: SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "confignochange", addmaps = { }) pass elif command == "status" or command == "" or not command: logging.info('Status request from %s', message['fromAddress']) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "status", addmaps = { 'email': userdata.email, 'domain': userdata.domain, 'active': "Yes" if userdata.active else "No", 'cansend': "Yes" if userdata.cansend else "No", 'cancharge': "Yes" if userdata.cancharge else "No", 'caninvoice': "Yes" if userdata.caninvoice else "No", 'pgp': "server" if userdata.pgp else "local", 'attachments': "Yes" if userdata.attachments else "No", 'expires': userdata.exp.strftime("%B %-d %Y"), 'masterpubkey_btc': userdata.masterpubkey_btc if userdata.masterpubkey_btc else "N/A", 'offset_btc': str(userdata.offset_btc) if userdata.masterpubkey_btc else "N/A", 'feeamount': str(userdata.feeamount) if userdata.masterpubkey_btc else "N/A", 'feecurrency': str(userdata.feecurrency) if userdata.masterpubkey_btc else "N/A", 'archive': "Yes" if userdata.archive else "No", 'flags': hex(userdata.flags), 'aliases': ', '.join(userdata.aliases) if userdata.aliases else "None" }) else: logging.info('Invalid command from %s', message['fromAddress']) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "command-invalid", addmaps = { 'command': command, 'email': userdata.email }) else: # attempt to register new user ## find requested username proposed_registration_user = base64.b64decode(message['subject']).lower() #full_registration_user = registration_user + '@' + BMConfig().get("bmgateway", "bmgateway", "domain_name") valid_one = re.match('^[\w]{4,20}$', proposed_registration_user) is not None valid_two = re.match('^[\w]{4,20}@' + BMConfig().get("bmgateway", "bmgateway", "domain_name") + '$', proposed_registration_user) is not None # strip domain if they sent it during registration if valid_one: full_registration_user = proposed_registration_user.lower() + '@' + BMConfig().get("bmgateway", "bmgateway", "domain_name") registration_user = proposed_registration_user.lower() elif valid_two: full_registration_user = proposed_registration_user.lower() registration_user = proposed_registration_user.split('@')[0].lower() else: logging.info('Invalid email address in registration request for %s', proposed_registration_user) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "registration-invalid", addmaps = { 'email': proposed_registration_user }) BMMessage.deleteStatic(bm_id) continue ## if username is valid check if it's available ## check if address is already registered to a username or is banned if is_banned_username(registration_user): logging.info('Banned email address in registration request for %s', registration_user) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "registration-duplicate", addmaps = { 'email': full_registration_user }) BMMessage.deleteStatic(bm_id) continue elif lib.user.GWUser(email = full_registration_user).check(): logging.info('Duplicate email address in registration request for %s', registration_user) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "registration-duplicate", addmaps = { 'email': full_registration_user }) BMMessage.deleteStatic(bm_id) continue logging.info('Received registration request for email address %s ', full_registration_user) lib.user.GWUser(empty = True).add(bm = message['fromAddress'], email = full_registration_user) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "registration-confirmed", addmaps = { 'email': full_registration_user }) ## if sent to the generic recipient or sender address elif field_in_list(message, BMAPI().address_list, 'toAddress', 'relay_address_label'): ## if user is not registered, purge userdata = lib.user.GWUser(bm = message['fromAddress']) if not userdata.check(): if BMConfig().get("bmgateway", "bmgateway", "allow_unregistered_senders"): bm_sender = message['fromAddress'] + '@' + BMConfig().get("bmgateway", "bmgateway", "domain_name") else: logging.warn('Purged bitmessage from non-registered user ' + message['fromAddress']) BMMessage.deleteStatic(bm_id) continue ## if user is registered, find their username @ domain else: bm_sender = userdata.email ## find outbound email address bm_receiver = re.findall(r'[\w\.\+-]+@[\w\.-]+\.[\w]+', base64.b64decode(message['subject'])) if len(bm_receiver) > 0: bm_receiver = bm_receiver[0] ## if there is no receiver mapping or the generic address didnt get a valid outbound email, deny it if not bm_receiver: # FIXME explain to sender what is whrong logging.warn('Received and purged bitmessage with unknown recipient (likely generic address and bad subject)') if BMConfig().get("bmgateway", "bmgateway", "respond_to_missing"): SendBMTemplate( sender = message['toAddress'], recipient = message['fromAddress'], template = "relay-missing-recipient", addmaps = { 'email': userdata.email, }) BMMessage.deleteStatic(bm_id) continue # expired or cannot send if (userdata.expired() or userdata.cansend == 0) and not \ (bm_receiver == BMConfig().get("bmgateway", "bmgateway", "bug_report_address_email")): # can still contact bugreport btcaddress, amount = lib.payment.payment_exists_domain (BMConfig().get("bmgateway", "bmgateway", "domain_name"), userdata.bm) # create new one if btcaddress == False: btcaddress, amount = lib.payment.create_invoice_domain (BMConfig().get("bmgateway", "bmgateway", "domain_name"), userdata.bm) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "accountexpired", addmaps = { 'btcuri': lib.payment.create_payment_uri(btcaddress, 'BTC', amount, BMConfig().get("bmgateway", "bmgateway", "companyname"), 'User ' + userdata.bm + " / " + userdata.email + ' subscription'), 'service': 'Subscription for ' + userdata.email + ' from ' + datetime.date.today().strftime("%B %-d %Y") + ' until ' + userdata.exp.strftime("%B %-d %Y"), 'email': userdata.email }) logging.warn("User " + message['fromAddress'] + " notified of payment requirement") BMMessage.deleteStatic(bm_id) continue bm_subject = base64.b64decode(message['subject']) ## handle removal of embedded MAILCHUCK-FROM:: tag for replies bm_subject = bm_subject.replace('MAILCHUCK-FROM::' + bm_receiver + ' | ', ''); ## remove email address from subject if field_in_list(message, BMAPI().address_list, 'toAddress', 'relay_address_label'): bm_subject = bm_subject.replace(bm_receiver, '') ## get message contents bm_body = base64.b64decode(message['message']) ## pad with a newline, otherwise it may look ugly if bm_body[-1:] != '\n': bm_body += '\n' ## send message and delete bitmessage, bitches if (float(userdata.lastrelay) + BMConfig().get("bmgateway", "bmgateway", "throttle") > time.time()): SendBMTemplate( sender = message['toAddress'], recipient = message['fromAddress'], template = "relay-throttle", addmaps = { 'email': userdata.email, 'throttledelta': str(int((float(userdata.lastrelay) + BMConfig().get("bmgateway", "bmgateway", "throttle") - time.time() + 60)/60)) }) logging.warn('Throttled %s', message['fromAddress']) BMMessage.deleteStatic(bm_id) continue else: retval = send_email(bm_receiver, bm_sender, bm_subject, bm_body, bm_id, userdata = userdata) if retval is None: logging.info('Relayed from %s to %s', message['fromAddress'], bm_receiver) else: if retval[0] >= 400 and retval[0] < 500: # do not delete, repeatable continue else: SendBMTemplate( sender = message['toAddress'], recipient = message['fromAddress'], template = "smtperror", addmaps = { 'emailrcpt': bm_receiver, 'errcode': retval[0], 'errmessage': retval[1] } ) ## remove message BMMessage.deleteStatic(bm_id) lib.bminbox.set_message_processed(bm_id) intcond.wait(BMConfig().get("bmgateway", "bmgateway", "process_interval")) intcond.release() logging.info("Leaving BM inbox checker loop")
def send_email(recipient, sender, subject, body, bm_id, userdata = None): ## open connection server = smtplib.SMTP('localhost') server.set_debuglevel(0) ## build message msg = MIMEMultipart() msg['From'] = sender msg['To'] = recipient msg['Subject'] = subject ## Signature if BMConfig().get("bmgateway", "bmgateway", "signature") is not None: body += "-- \n" + \ BMConfig().get("bmgateway", "bmgateway", "signature") + \ "\n" enc_body = None sender_key = None recipient_key = None sign = BMConfig().get("bmgateway", "pgp", "sign") encrypt = BMConfig().get("bmgateway", "pgp", "encrypt") if userdata: if userdata.expired(): sign = False encrypt = False else: # only override if not expired and pgp allowed globally if sign: sign = (userdata.pgp == 1) if encrypt: encrypt = (userdata.pgp == 1) #TODO find out if already encrypted/signed ## generate a signing key if we dont have one if sign: if not lib.gpg.check_key(sender, whatreturn="key", operation="sign"): lib.gpg.create_primary_key(sender) sender_key = lib.gpg.check_key(sender, whatreturn="key", operation="sign") if not sender_key: logging.error('Could not find or upload user\'s keyid: %s', sender) ## search for recipient PGP key if encrypt: # if lib.gpg.find_key(recipient): recipient_key = lib.gpg.check_key(recipient, whatreturn="key", operation="encrypt") if not recipient_key: logging.info('Could not find recipient\'s keyid, not encrypting: %s', recipient) # make sure sender has an encryption key if not lib.gpg.check_key(sender, whatreturn="key", operation="encrypt"): if not lib.gpg.check_key(sender, whatreturn="key", operation="sign"): lib.gpg.create_primary_key(sender) lib.gpg.create_subkey(sender) if sender_key and recipient_key: enc_body = lib.gpg.encrypt_text(body, recipient_key, sender_key) logging.info('Encrypted and signed outbound mail from %s to %s', sender, recipient) elif recipient_key: enc_body = lib.gpg.encrypt_text(body, recipient_key) logging.info('Encrypted outbound mail from %s to %s', sender, recipient) elif sender_key and not recipient == BMConfig().get("bmgateway", "bmgateway", "bug_report_address_email"): logging.info('Signed outbound mail from %s to %s', sender, recipient) enc_body = lib.gpg.sign_text(body, sender_key) ## only encrypt if the operation was successful if enc_body: body = enc_body text = body ## encode as needed body = MIMEText(body, 'plain') ## attach body with correct encoding msg.attach(body) text = msg.as_string() ## send message try: status = server.sendmail(sender, recipient, text, [], ["NOTIFY=SUCCESS,FAILURE,DELAY", "ORCPT=rfc822;" + recipient]) logging.info('Sent email from %s to %s', sender, recipient) BMMessage.deleteStatic(bm_id, folder = "inbox") ## send failed except smtplib.SMTPException as e: logging.error('Could not send email from %s to %s: %s', sender, recipient, e) server.quit() for rcpt in e.recipients: return e.recipients[rcpt] server.quit() return
def check_bminbox(intcond): global interrupted ## get all messages #all_messages = json.loads(api['conn'].getAllInboxMessages())['inboxMessages'] logging.info("Entering BM inbox checker loop") intcond.acquire() while not interrupted: all_messages = get_inbox() ## if no messages if not all_messages: try: intcond.wait(BMConfig().get("bmgateway", "bmgateway", "process_interval")) except KeyboardInterrupt: break continue ## loop through messages to find unread for a_message in all_messages: ## if already read, delete and break if a_message['read'] == 1: BMMessage.deleteStatic(a_message['msgid']) continue ## if the message is unread, load it by ID to trigger the read flag message = json.loads(BMAPI().conn().getInboxMessageByID(a_message['msgid'], False))['inboxMessage'][0] ## if a blank message was returned if not message: logging.error('API returned blank message when requesting a message by msgID') delete_bitmessage_inbox(bm_id) BMMessage.deleteStatic(a_message['msgid']) continue ## find message ID bm_id = message['msgid'] ## check if receive address is a DEregistration request if field_in_list(message, BMAPI().address_list, 'toAddress', 'deregistration_address_label'): ## check if address is registered userdata = lib.user.GWUser(bm = message['fromAddress']) ## if the sender is actually registered and wants to deregister if userdata.check(): ## process deregistration logging.info('Processed deregistration request for user ' + userdata.email) delete_address(message['fromAddress']) ## send deregistration confirmation email SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "deregistration_address_label")), recipient = message['fromAddress'], template = "deregistration-confirmed", addmaps = { 'email': userdata.email }) ## bogus deregistration request else: logging.warn('Purged malicious deregistration bitmessage from ' + message['fromAddress']) ## check if receive address is a registration request elif field_in_list(message, BMAPI().address_list, 'toAddress', 'registration_address_label'): userdata = lib.user.GWUser(bm = message['fromAddress']) if userdata.check(): # status, config, etc command = base64.b64decode(message['subject']).lower() if command == "blabla": logging.info('Blabla request from %s', message['fromAddress']) elif command == "status" or command == "" or not command: logging.info('Status request from %s', message['fromAddress']) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "status", addmaps = { 'email': userdata.email, 'domain': userdata.domain, 'active': "Yes" if userdata.active else "No", 'cansend': "Yes" if userdata.cansend else "No", 'cancharge': "Yes" if userdata.cancharge else "No", 'caninvoice': "Yes" if userdata.caninvoice else "No", 'pgp': "Yes" if userdata.pgp else "No", 'attachments': "Yes" if userdata.attachments else "No", 'expires': userdata.exp.strftime("%B %-d %Y"), 'masterpubkey_btc': userdata.masterpubkey_btc if userdata.masterpubkey_btc else "N/A", 'offset_btc': str(userdata.offset_btc) if userdata.masterpubkey_btc else "N/A", 'feeamount': str(userdata.feeamount) if userdata.masterpubkey_btc else "N/A", 'feecurrency': str(userdata.feecurrency) if userdata.masterpubkey_btc else "N/A", 'archive': "Yes" if userdata.archive else "No", 'flags': userdata.flags }) else: logging.info('Invalid command from %s', message['fromAddress']) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "command-invalid", addmaps = { 'email': proposed_registration_user }) else: # attempt to register new user ## find requested username proposed_registration_user = base64.b64decode(message['subject']).lower() #full_registration_user = registration_user + '@' + BMConfig().get("bmgateway", "bmgateway", "domain_name") valid_one = re.match('^[\w]{4,20}$', proposed_registration_user) is not None valid_two = re.match('^[\w]{4,20}@' + BMConfig().get("bmgateway", "bmgateway", "domain_name") + '$', proposed_registration_user) is not None # strip domain if they sent it during registration if valid_one: full_registration_user = proposed_registration_user.lower() + '@' + BMConfig().get("bmgateway", "bmgateway", "domain_name") registration_user = proposed_registration_user.lower() elif valid_two: full_registration_user = proposed_registration_user.lower() registration_user = proposed_registration_user.split('@')[0].lower() else: logging.info('Invalid email address in registration request for %s', proposed_registration_user) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "registration-invalid", addmaps = { 'email': proposed_registration_user }) BMMessage.deleteStatic(bm_id) continue ## if username is valid check if it's available ## check if address is already registered to a username or is banned if is_banned_username(registration_user): logging.info('Banned email address in registration request for %s', registration_user) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "registration-duplicate", addmaps = { 'email': full_registration_user }) BMMessage.deleteStatic(bm_id) continue elif lib.user.GWUser(email = full_registration_user).check(): logging.info('Duplicate email address in registration request for %s', registration_user) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "registration-duplicate", addmaps = { 'email': full_registration_user }) BMMessage.deleteStatic(bm_id) continue logging.info('Received registration request for email address %s ', full_registration_user) lib.user.GWUser(empty = True).add(bm = message['fromAddress'], email = full_registration_user) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "registration-confirmed", addmaps = { 'email': full_registration_user }) ## if sent to the generic recipient or sender address elif field_in_list(message, BMAPI().address_list, 'toAddress', 'relay_address_label'): ## if user is not registered, purge userdata = lib.user.GWUser(bm = message['fromAddress']) if not userdata.check(): if BMConfig().get("bmgateway", "bmgateway", "allow_unregistered_senders"): bm_sender = message['fromAddress'] + '@' + BMConfig().get("bmgateway", "bmgateway", "domain_name") else: logging.warn('Purged bitmessage from non-registered user ' + message['fromAddress']) BMMessage.deleteStatic(bm_id) continue ## if user is registered, find their username @ domain else: bm_sender = userdata.email ## find outbound email address bm_receiver = re.findall(r'[\w\.\+-]+@[\w\.-]+\.[\w]+', base64.b64decode(message['subject'])) if len(bm_receiver) > 0: bm_receiver = bm_receiver[0] ## if there is no receiver mapping or the generic address didnt get a valid outbound email, deny it if not bm_receiver: # FIXME explain to sender what is whrong logging.warn('Received and purged bitmessage with unknown recipient (likely generic address and bad subject)') if BMConfig().get("bmgateway", "bmgateway", "respond_to_missing"): SendBMTemplate( sender = message['toAddress'], recipient = message['fromAddress'], template = "relay-missing-recipient", addmaps = { 'email': userdata.email, }) BMMessage.deleteStatic(bm_id) continue # expired or cannot send if (userdata.expired() or userdata.cansend == 0) and not \ (bm_receiver == BMConfig().get("bmgateway", "bmgateway", "bug_report_address_email")): # can still contact bugreport btcaddress, amount = lib.payment.payment_exists_domain (BMConfig().get("bmgateway", "bmgateway", "domain_name"), userdata.bm) # create new one if btcaddress == False: btcaddress, amount = lib.payment.create_invoice_domain (BMConfig().get("bmgateway", "bmgateway", "domain_name"), userdata.bm) SendBMTemplate( sender = BMAPI().get_address(BMConfig().get("bmgateway", "bmgateway", "registration_address_label")), recipient = message['fromAddress'], template = "accountexpired", addmaps = { 'btcuri': lib.payment.create_payment_uri(btcaddress, 'BTC', amount, BMConfig().get("bmgateway", "bmgateway", "companyname"), 'User ' + userdata.bm + " / " + userdata.email + ' subscription'), 'service': 'Subscription for ' + userdata.email + ' from ' + datetime.date.today().strftime("%B %-d %Y") + ' until ' + userdata.exp.strftime("%B %-d %Y"), 'email': userdata.email }) logging.warn("User " + message['fromAddress'] + " notified of payment requirement") BMMessage.deleteStatic(bm_id) continue bm_subject = base64.b64decode(message['subject']) ## handle removal of embedded MAILCHUCK-FROM:: tag for replies bm_subject = bm_subject.replace('MAILCHUCK-FROM::' + bm_receiver + ' | ', ''); ## remove email address from subject if field_in_list(message, BMAPI().address_list, 'toAddress', 'relay_address_label'): bm_subject = bm_subject.replace(bm_receiver, '') ## get message contents bm_body = base64.b64decode(message['message']) ## send message and delete bitmessage, bitches if (float(userdata.lastrelay) + BMConfig().get("bmgateway", "bmgateway", "throttle") > time.time()): SendBMTemplate( sender = message['toAddress'], recipient = message['fromAddress'], template = "relay-throttle", addmaps = { 'email': userdata.email, 'throttledelta': str(int((float(userdata.lastrelay) + BMConfig().get("bmgateway", "bmgateway", "throttle") - time.time() + 60)/60)) }) logging.warn('Throttled %s', message['fromAddress']) BMMessage.deleteStatic(bm_id) continue else: send_email(bm_receiver, bm_sender, bm_subject, bm_body, bm_id, userdata = userdata) logging.info('Relayed from %s to %s', message['fromAddress'], bm_receiver) ## remove message BMMessage.deleteStatic(bm_id) intcond.wait(BMConfig().get("bmgateway", "bmgateway", "process_interval")) intcond.release() logging.info("Leaving BM inbox checker loop")
def send_email(recipient, sender, subject, body, bm_id, userdata = None): ## open connection server = smtplib.SMTP('localhost') server.set_debuglevel(0) ## build message msg = MIMEMultipart() msg['From'] = sender msg['To'] = recipient msg['Subject'] = subject enc_body = None sender_key = None recipient_key = None sign = BMConfig().get("bmgateway", "pgp", "sign") encrypt = BMConfig().get("bmgateway", "pgp", "encrypt") if userdata: if userdata.expired(): sign = False encrypt = False else: # only override if not expired and pgp allowed globally if sign: sign = (userdata.pgp == 1) if encrypt: encrypt = (userdata.pgp == 1) #TODO find out if already encrypted/signed ## generate a signing key if we dont have one if sign: if not lib.gpg.check_key(sender, whatreturn="key", operation="sign"): lib.gpg.create_primary_key(sender) sender_key = lib.gpg.check_key(sender, whatreturn="key", operation="sign") if not sender_key: logging.error('Could not find or upload user\'s keyid: %s', sender) ## search for recipient PGP key if encrypt: # if lib.gpg.find_key(recipient): recipient_key = lib.gpg.check_key(recipient, whatreturn="key", operation="encrypt") if not recipient_key: logging.info('Could not find recipient\'s keyid, not encrypting: %s', recipient) # make sure sender has an encryption key if not lib.gpg.check_key(sender, whatreturn="key", operation="encrypt"): if not lib.gpg.check_key(sender, whatreturn="key", operation="sign"): lib.gpg.create_primary_key(sender) lib.gpg.create_subkey(sender) if sender_key and recipient_key: enc_body = lib.gpg.encrypt_text(body, recipient_key, sender_key) logging.info('Encrypted and signed outbound mail from %s to %s', sender, recipient) elif recipient_key: enc_body = lib.gpg.encrypt_text(body, recipient_key) logging.info('Encrypted outbound mail from %s to %s', sender, recipient) elif sender_key and not recipient == BMConfig().get("bmgateway", "bmgateway", "bug_report_address_email"): logging.info('Signed outbound mail from %s to %s', sender, recipient) enc_body = lib.gpg.sign_text(body, sender_key) ## only encrypt if the operation was successful if enc_body: body = enc_body text = body ## encode as needed body = MIMEText(body, 'plain') ## attach body with correct encoding msg.attach(body) text = msg.as_string() ## send message try: status = server.sendmail(sender, recipient, text, [], ["NOTIFY=SUCCESS,FAILURE,DELAY", "ORCPT=rfc822;" + recipient]) logging.info('Sent email from %s to %s', sender, recipient) BMMessage.deleteStatic(bm_id, folder = "inbox") ## send failed except smtplib.SMTPException as e: logging.error('Could not send email from %s to %s: %s', sender, recipient, e) server.quit()