def schedule_exception_email(exception_text, *args): try: from globaleaks.transactions import schedule_email if not hasattr(GLSettings.memory_copy, 'notif'): log.err( "Error: Cannot send mail exception before complete initialization." ) return if GLSettings.exceptions_email_count >= GLSettings.exceptions_email_hourly_limit: return exception_text = (exception_text % args) if args else exception_text sha256_hash = sha256(bytes(exception_text)) if sha256_hash not in GLSettings.exceptions: GLSettings.exceptions[sha256_hash] = 1 else: GLSettings.exceptions[sha256_hash] += 1 if GLSettings.exceptions[sha256_hash] > 5: log.err( "Exception mail suppressed for (%s) [reason: threshold exceeded]", sha256_hash) return GLSettings.exceptions_email_count += 1 mail_subject = "GlobaLeaks Exception" delivery_list = GLSettings.memory_copy.notif.exception_delivery_list if GLSettings.devel_mode: mail_subject += " [%s]" % GLSettings.developer_name delivery_list = [("*****@*****.**", '')] exception_text = bytes("Platform: %s (%s)\nVersion: %s\n\n%s" \ % (GLSettings.memory_copy.hostname, GLSettings.memory_copy.onionservice, __version__, exception_text)) for mail_address, pub_key in delivery_list: mail_body = exception_text # Opportunisticly encrypt the mail body. NOTE that mails will go out # unencrypted if one address in the list does not have a public key set. if pub_key: mail_body = encrypt_message(pub_key, mail_body) # avoid waiting for the notification to send and instead rely on threads to handle it schedule_email(mail_address, mail_subject, mail_body) except Exception as excep: # Avoid raising exception inside email logic to avoid chaining errors log.err("Unexpected exception in send_exception_mail: %s", excep)
def format_and_send(store, user_desc, template_vars): subject, body = Templating().get_mail_subject_and_body(template_vars) if user_desc['pgp_key_public']: body = encrypt_message(user_desc['pgp_key_public'], body) store.add(models.Mail({ 'address': user_desc['mail_address'], 'subject': subject, 'body': body }))
def process_mail_creation(self, store, data): user_id = data['user']['id'] # Do not spool emails if the receiver has opted out of ntfns for this tip. if not data['tip']['enable_notifications']: log.debug("Discarding emails for %s due to receiver's preference.", user_id) return # https://github.com/globaleaks/GlobaLeaks/issues/798 # TODO: the current solution is global and configurable only by the admin sent_emails = State.get_mail_counter(user_id) if sent_emails >= State.tenant_cache[ 1].notif.notification_threshold_per_hour: log.debug( "Discarding emails for receiver %s due to threshold already exceeded for the current hour", user_id) return State.increment_mail_counter(user_id) if sent_emails >= State.tenant_cache[ 1].notif.notification_threshold_per_hour: log.info( "Reached threshold of %d emails with limit of %d for receiver %s", sent_emails, State.tenant_cache[1].notif.notification_threshold_per_hour, user_id) # simply changing the type of the notification causes # to send the notification_limit_reached data['type'] = u'receiver_notification_limit_reached' data['notification'] = self.serialize_config(store, 'notification', data['user']['language']) data['node'] = self.serialize_config(store, 'node', data['user']['language']) if not data['node']['allow_unencrypted'] and len( data['user']['pgp_key_public']) == 0: return subject, body = Templating().get_mail_subject_and_body(data) # If the receiver has encryption enabled encrypt the mail body if data['user']['pgp_key_public']: body = encrypt_message(data['user']['pgp_key_public'], body) store.add( models.Mail({ 'address': data['user']['mail_address'], 'subject': subject, 'body': body }))
def certificate_mail_creation(self, store, expiration_date): for user_desc in db_get_admin_users(store): lang = user_desc['language'] template_vars = { 'type': 'https_certificate_expiration', 'expiration_date': expiration_date, 'node': db_admin_serialize_node(store, lang), 'notification': db_get_notification(store, lang) } subject, body = Templating().get_mail_subject_and_body(template_vars) # encrypt the notification if the admin has configured the issue. if user_desc['pgp_key_public']: body = encrypt_message(user_desc['pgp_key_public'], body) store.add(models.Mail({ 'address': user_desc['mail_address'], 'subject': subject, 'body': body }))