def srs_forward(self, addr, domain): # if domain is hostname, virtual mail domain or srs_domain, do not rewrite. if domain == settings.srs_domain: reply = TCP_REPLIES['not_exist'] + 'Domain is srs_domain, bypassed.' return reply elif domain == fqdn: reply = TCP_REPLIES['not_exist'] + 'Domain is server hostname, bypassed.' return reply else: _is_local_domain = False try: conn_vmail = self.db_conns['conn_vmail'] _is_local_domain = is_local_domain(conn=conn_vmail, domain=domain) except Exception as e: logger.error("{} Error while verifying domain: {}".format(self.log_prefix, repr(e))) if _is_local_domain: reply = TCP_REPLIES['not_exist'] + 'Domain is a local mail domain, bypassed.' return reply else: possible_domains = [] _splited_parts = domain.split('.') _length = len(_splited_parts) for i in range(_length): _part1 = '.'.join(_splited_parts[-i:]) _part2 = '.' + _part1 possible_domains += [_part1, _part2] conn_iredapd = self.db_conns['conn_iredapd'] sql = """SELECT id FROM srs_exclude_domains WHERE domain IN %s LIMIT 1""" % sqlquote(list(possible_domains)) logger.debug("{} [SQL] Query srs_exclude_domains: {}".format(self.log_prefix, sql)) try: qr = conn_iredapd.execute(sql) sql_record = qr.fetchone() logger.debug("{} [SQL] Query result: {}".format(self.log_prefix, sql_record)) except Exception as e: logger.debug("{} Error while querying SQL: {}".format(self.log_prefix, repr(e))) reply = TCP_REPLIES['not_exist'] return reply if sql_record: reply = TCP_REPLIES['not_exist'] + 'Domain is explicitly excluded, bypassed.' return reply else: try: new_addr = str(self.srslib_instance.forward(addr, settings.srs_domain)) logger.info("{} rewrote: {} -> {}".format(self.log_prefix, addr, new_addr)) reply = TCP_REPLIES['success'] + new_addr return reply except Exception as e: logger.debug("{} Error while generating forward address: {}".format(self.log_prefix, repr(e))) # Return original address. reply = TCP_REPLIES['not_exist'] return reply
def restriction(**kwargs): conn = kwargs["conn_amavisd"] conn_vmail = kwargs["conn_vmail"] if not conn: logger.error("Error, no valid Amavisd database connection.") return SMTP_ACTIONS["default"] # Get sender and recipient sender = kwargs["sender_without_ext"] sender_domain = kwargs["sender_domain"] recipient = kwargs["recipient_without_ext"] recipient_domain = kwargs["recipient_domain"] if kwargs["sasl_username"]: # Use sasl_username as sender for outgoing email sender = kwargs["sasl_username"] sender_domain = kwargs["sasl_username_domain"] if not sender: logger.debug("SKIP: no sender address.") return SMTP_ACTIONS["default"] if sender == recipient: logger.debug("SKIP: Sender is same as recipient.") return SMTP_ACTIONS["default"] valid_senders = utils.get_policy_addresses_from_email(mail=sender) valid_recipients = utils.get_policy_addresses_from_email(mail=recipient) if not kwargs["sasl_username"]: # Sender `username@*` sender_username = sender.split("@", 1)[0] if "+" in sender_username: valid_senders.append(sender_username.split("+", 1)[0] + "@*") else: valid_senders.append(sender_username + "@*") # Append original IP address client_address = kwargs["client_address"] valid_senders.append(client_address) # Append all possible wildcast IP addresses if utils.is_ipv4(client_address): valid_senders += utils.wildcard_ipv4(client_address) alias_target_sender_domain = get_alias_target_domain( alias_domain=sender_domain, conn=conn_vmail) if alias_target_sender_domain: _mail = sender.split("@", 1)[0] + "@" + alias_target_sender_domain valid_senders += utils.get_policy_addresses_from_email(mail=_mail) alias_target_rcpt_domain = get_alias_target_domain( alias_domain=recipient_domain, conn=conn_vmail) if alias_target_rcpt_domain: _mail = recipient.split("@", 1)[0] + "@" + alias_target_rcpt_domain valid_recipients += utils.get_policy_addresses_from_email(mail=_mail) logger.debug("Possible policy senders: {}".format(valid_senders)) logger.debug("Possible policy recipients: {}".format(valid_recipients)) id_of_client_cidr_networks = [] client_cidr_network_checked = False # Outbound if kwargs["sasl_username"]: logger.debug("Apply wblist for outbound message.") id_of_local_addresses = get_id_of_local_addresses(conn, valid_senders) id_of_ext_addresses = [] if id_of_local_addresses: id_of_ext_addresses = get_id_of_external_addresses( conn, valid_recipients) id_of_client_cidr_networks = get_id_of_possible_cidr_network( conn, client_address) client_cidr_network_checked = True action = apply_outbound_wblist(conn, sender_ids=id_of_local_addresses + id_of_client_cidr_networks, recipient_ids=id_of_ext_addresses) if not action.startswith("DUNNO"): return action check_inbound = False if not kwargs["sasl_username"]: check_inbound = True if (not check_inbound) and kwargs["sasl_username"] and ( sender_domain == recipient_domain): # Local user sends to another user in same domain check_inbound = True if not check_inbound: rcpt_domain_is_local = is_local_domain(conn=conn_vmail, domain=recipient_domain, include_alias_domain=False) if alias_target_rcpt_domain or rcpt_domain_is_local: # Local user sends to another local user in different domain check_inbound = True if check_inbound: logger.debug("Apply wblist for inbound message.") id_of_ext_addresses = [] id_of_local_addresses = get_id_of_local_addresses( conn, valid_recipients) if id_of_local_addresses: id_of_ext_addresses = get_id_of_external_addresses( conn, valid_senders) if not client_cidr_network_checked: id_of_client_cidr_networks = get_id_of_possible_cidr_network( conn, client_address) action = apply_inbound_wblist(conn, sender_ids=id_of_ext_addresses + id_of_client_cidr_networks, recipient_ids=id_of_local_addresses) if not action.startswith("DUNNO"): return action return SMTP_ACTIONS["default"]
def restriction(**kwargs): sasl_username = kwargs['sasl_username'] sasl_username_user = sasl_username.split('@', 1)[0] sasl_username_domain = kwargs['sasl_username_domain'] sender = kwargs['sender_without_ext'] sender_name = '' sender_domain = '' if sender: (sender_name, sender_domain) = sender.split('@', 1) # Leave this to plugin `reject_null_sender`. if sasl_username and not sender: return SMTP_ACTIONS['default'] recipient_domain = kwargs['recipient_domain'] client_address = kwargs['client_address'] real_sasl_username = sasl_username real_sender = sender conn = kwargs['conn_vmail'] # Check emails sent from external network. if not sasl_username: logger.debug('Not an authenticated sender (no sasl_username).') # Bypass trusted networks. # NOTE: if sender sent email through SOGo, smtp session may not # have `sasl_username`. if is_trusted_client(client_address): logger.debug('Bypass trusted client.') return SMTP_ACTIONS['default'] if not check_forged_sender: logger.debug('Skip forged sender checks.') return SMTP_ACTIONS['default'] # Bypass allowed forged sender. if sender in allowed_forged_senders or \ sender_domain in allowed_forged_senders or \ sender_name + '@*' in allowed_forged_senders: logger.debug('Bypass allowed forged sender.') return SMTP_ACTIONS['default'] _is_local_sender_domain = False if sender_domain == recipient_domain: logger.debug('Sender domain is same as recipient domain.') _is_local_sender_domain = True else: if is_local_domain(conn=conn, domain=sender_domain, include_backupmx=False): logger.debug( 'Sender domain is hosted locally, smtp authentication is required.' ) _is_local_sender_domain = True else: logger.debug('Sender domain is NOT hosted locally.') if _is_local_sender_domain: if settings.CHECK_SPF_IF_LOGIN_MISMATCH: logger.debug( 'Check whether client is allowed smtp server against DNS SPF record.' ) # Query DNS to get IP addresses/networks listed in SPF # record of sender domain, reject if not match. if dnsspf.is_allowed_server_in_spf(sender_domain=sender_domain, ip=client_address): logger.debug( 'Sender server is listed in DNS SPF record, bypassed.') return SMTP_ACTIONS['default'] else: logger.debug( 'Sender server is NOT listed in DNS SPF record.') logger.debug('Sender is considered as forged, rejecting') return SMTP_ACTIONS['reject_forged_sender'] else: return SMTP_ACTIONS['default'] # Check emails sent by authenticated users. logger.debug('Sender: %s, SASL username: %s' % (sender, sasl_username)) if sender == sasl_username: logger.debug('SKIP: sender == sasl username.') return SMTP_ACTIONS['default'] # # sender != sasl_username # # If no access settings available, reject directly. if not (allowed_senders or is_strict or allow_list_member): logger.debug('No allowed senders in config file.') return action_reject # Check explicitly allowed senders if allowed_senders: logger.debug('Allowed SASL senders: %s' % ', '.join(allowed_senders)) if sasl_username in allowed_senders: logger.debug('Sender SASL username is explicitly allowed.') return SMTP_ACTIONS['default'] elif sasl_username_domain in allowed_senders: logger.debug('Sender domain name is explicitly allowed.') return SMTP_ACTIONS['default'] elif ('@' + sasl_username_domain in allowed_senders) or ('@.' in allowed_senders): # Restrict to send as users under SAME domain if sasl_username_domain == sender_domain: return SMTP_ACTIONS['default'] else: # Note: not reject email here, still need to check other access settings. logger.debug( 'Sender is not allowed to send email as other user (ALLOWED_LOGIN_MISMATCH_SENDERS).' ) # Check whether sender is a member of mlmmj mailing list. _check_mlmmj_ml = False # Check alias domains and user alias addresses if is_strict or allow_list_member: if is_strict: logger.debug( 'Apply strict restriction (ALLOWED_LOGIN_MISMATCH_STRICTLY=True).' ) if allow_list_member: logger.debug( 'Apply list/alias member restriction (ALLOWED_LOGIN_MISMATCH_LIST_MEMBER=True).' ) if settings.backend == 'ldap': filter_user_alias = '(&(objectClass=mailUser)(mail=%s)(shadowAddress=%s))' % ( sasl_username, sender) filter_list_member = '(&(objectClass=mailUser)(|(mail=%s)(shadowAddress=%s))(memberOfGroup=%s))' % ( sasl_username, sasl_username, sender) filter_alias_member = '(&(objectClass=mailAlias)(|(mail=%s)(shadowAddress=%s))(mailForwardingAddress=%s))' % ( sender, sender, sasl_username) if is_strict and (not allow_list_member): # Query mail account directly query_filter = filter_user_alias success_msg = 'Sender is an user alias address.' elif (not is_strict) and allow_list_member: query_filter = '(|' + filter_list_member + filter_alias_member + ')' success_msg = 'Sender (%s) is member of mail list/alias (%s).' % ( sasl_username, sender) else: # (is_strict and allow_list_member) query_filter = '(|' + filter_user_alias + filter_list_member + filter_alias_member + ')' success_msg = 'Sender (%s) is an user alias address or list/alias member (%s).' % ( sasl_username, sender) qr = conn_utils.get_account_ldif(conn=conn, account=sasl_username, query_filter=query_filter, attrs=['dn']) (_dn, _ldif) = qr if _dn: logger.debug(success_msg) return SMTP_ACTIONS['default'] else: logger.debug( 'Sender is neither user alias address nor member of list/alias.' ) # Check mlmmj query_filter = "(&(objectClass=mailList)(enabledService=mlmmj)(accountStatus=active))" qr = conn_utils.get_account_ldif(conn=conn, account=sender, query_filter=query_filter, attrs=['dn']) (_dn, _ldif) = qr if _dn: _check_mlmmj_ml = True elif settings.backend in ['mysql', 'pgsql']: if is_strict: # Get per-user alias addresses sql = """SELECT address FROM forwardings WHERE address=%s AND forwarding=%s AND is_alias=1 LIMIT 1""" % (sqlquote(sender), sqlquote(real_sasl_username)) logger.debug('[SQL] query per-user alias address: \n%s' % sql) qr = conn.execute(sql) sql_record = qr.fetchone() logger.debug('SQL query result: %s' % str(sql_record)) if sql_record: logger.debug( 'Sender %s is an alias address of smtp auth username %s.' % (sender, real_sasl_username)) return SMTP_ACTIONS['default'] else: logger.debug('No per-user alias address found.') # Get alias domains if sender_domain != sasl_username_domain: sql = """SELECT alias_domain FROM alias_domain WHERE alias_domain=%s AND target_domain=%s LIMIT 1""" % (sqlquote(sender_domain), sqlquote(sasl_username_domain)) logger.debug('[SQL] query alias domains: \n%s' % sql) qr = conn.execute(sql) sql_record = qr.fetchone() logger.debug('SQL query result: %s' % str(sql_record)) if not sql_record: logger.debug('No alias domain found.') else: logger.debug( 'Sender domain %s is an alias domain of %s.' % (sender_domain, sasl_username_domain)) real_sasl_username = sasl_username_user + '@' + sasl_username_domain real_sender = sender_name + '@' + sasl_username_domain # sender_domain is one of alias domains if sender_name != sasl_username_user: logger.debug( 'Sender is not an user alias address.') else: logger.debug( 'Sender is an alias address of sasl username.') return SMTP_ACTIONS['default'] if allow_list_member: # Get alias members sql = """SELECT forwarding FROM forwardings WHERE address=%s AND forwarding=%s AND is_list=1 AND active=1 LIMIT 1""" % (sqlquote(real_sender), sqlquote(real_sasl_username)) logger.debug( '[SQL] query members of mail alias account (%s): \n%s' % (real_sender, sql)) qr = conn.execute(sql) sql_record = qr.fetchone() logger.debug('SQL query result: %s' % str(sql_record)) if sql_record: logger.debug( 'SASL username (%s) is a member of mail alias (%s).' % (sasl_username, sender)) return SMTP_ACTIONS['default'] else: logger.debug('No such mail alias account.') # Check subscribeable (mlmmj) mailing list. sql = """SELECT id FROM maillists WHERE address=%s AND active=1 LIMIT 1""" % sqlquote( real_sender) logger.debug('[SQL] query mailing list account (%s): \n%s' % (real_sender, sql)) qr = conn.execute(sql) sql_record = qr.fetchone() logger.debug('SQL query result: %s' % str(sql_record)) if sql_record: _check_mlmmj_ml = True else: logger.debug('No such mailing list account.') if _check_mlmmj_ml: # Perform mlmmjadmin query. api_auth_token = settings.mlmmjadmin_api_auth_token if api_auth_token and settings.mlmmjadmin_api_endpoint: _api_endpoint = '/'.join([ settings.mlmmjadmin_api_endpoint, real_sender, 'has_subscriber', sasl_username ]) api_headers = { settings.MLMMJADMIN_API_AUTH_TOKEN_HEADER_NAME: api_auth_token } logger.debug('mlmmjadmin api endpoint: {0}'.format(_api_endpoint)) logger.debug('mlmmjadmin api headers: {0}'.format(api_headers)) try: r = requests.get(_api_endpoint, headers=api_headers, verify=False) _json = r.json() if _json['_success']: logger.debug( 'SASL username (%s) is a member of mailing list (%s).' % (sasl_username, sender)) return SMTP_ACTIONS['default'] except Exception as e: logger.error( "Error while querying mlmmjadmin api: {0}".format(e)) return action_reject
def restriction(**kwargs): conn = kwargs['conn_amavisd'] conn_vmail = kwargs['conn_vmail'] if not conn: logger.error('Error, no valid Amavisd database connection.') return SMTP_ACTIONS['default'] # Get sender and recipient sender = kwargs['sender_without_ext'] sender_domain = kwargs['sender_domain'] recipient = kwargs['recipient_without_ext'] recipient_domain = kwargs['recipient_domain'] if kwargs['sasl_username']: # Use sasl_username as sender for outgoing email sender = kwargs['sasl_username'] sender_domain = kwargs['sasl_username_domain'] if not sender: logger.debug('SKIP: no sender address.') return SMTP_ACTIONS['default'] if sender == recipient: logger.debug('SKIP: Sender is same as recipient.') return SMTP_ACTIONS['default'] valid_senders = get_policy_addresses_from_email(mail=sender) valid_recipients = get_policy_addresses_from_email(mail=recipient) if not kwargs['sasl_username']: # Sender 'username@*' sender_username = sender.split('@', 1)[0] if '+' in sender_username: valid_senders.append(sender_username.split('+', 1)[0] + '@*') else: valid_senders.append(sender_username + '@*') # Append original IP address client_address = kwargs['client_address'] valid_senders.append(client_address) # Append all possible wildcast IP addresses if is_ipv4(client_address): valid_senders += wildcard_ipv4(client_address) alias_target_sender_domain = get_alias_target_domain( alias_domain=sender_domain, conn=conn_vmail) if alias_target_sender_domain: _mail = sender.split('@', 1)[0] + '@' + alias_target_sender_domain valid_senders += get_policy_addresses_from_email(mail=_mail) alias_target_rcpt_domain = get_alias_target_domain( alias_domain=recipient_domain, conn=conn_vmail) if alias_target_rcpt_domain: _mail = recipient.split('@', 1)[0] + '@' + alias_target_rcpt_domain valid_recipients += get_policy_addresses_from_email(mail=_mail) logger.debug('Possible policy senders: {0}'.format(valid_senders)) logger.debug('Possible policy recipients: {0}'.format(valid_recipients)) check_outbound = False if (not check_outbound) and kwargs['sasl_username']: check_outbound = True sender_domain_is_local = is_local_domain(conn=conn_vmail, domain=sender_domain, include_alias_domain=False) if (not check_outbound) and (alias_target_sender_domain or sender_domain_is_local): check_outbound = True id_of_client_cidr_networks = [] client_cidr_network_checked = False # Outbound if check_outbound: logger.debug('Apply wblist for outbound message.') id_of_local_addresses = get_id_of_local_addresses(conn, valid_senders) id_of_ext_addresses = [] if id_of_local_addresses: id_of_ext_addresses = get_id_of_external_addresses( conn, valid_recipients) id_of_client_cidr_networks = get_id_of_possible_cidr_network( conn, client_address) client_cidr_network_checked = True action = apply_outbound_wblist(conn, sender_ids=id_of_local_addresses + id_of_client_cidr_networks, recipient_ids=id_of_ext_addresses) if not action.startswith('DUNNO'): return action check_inbound = False if (not check_inbound) and (not kwargs['sasl_username']): check_inbound = True if (not check_inbound) and kwargs['sasl_username'] and ( sender_domain == recipient_domain): # Local user sends to another user in same domain check_inbound = True rcpt_domain_is_local = is_local_domain(conn=conn_vmail, domain=recipient_domain, include_alias_domain=False) if (not check_inbound) and (alias_target_rcpt_domain or rcpt_domain_is_local): # Local user sends to another local user in different domain check_inbound = True if check_inbound: logger.debug('Apply wblist for inbound message.') id_of_ext_addresses = [] id_of_local_addresses = get_id_of_local_addresses( conn, valid_recipients) if id_of_local_addresses: id_of_ext_addresses = get_id_of_external_addresses( conn, valid_senders) if not client_cidr_network_checked: id_of_client_cidr_networks = get_id_of_possible_cidr_network( conn, client_address) action = apply_inbound_wblist(conn, sender_ids=id_of_ext_addresses + id_of_client_cidr_networks, recipient_ids=id_of_local_addresses) if not action.startswith('DUNNO'): return action return SMTP_ACTIONS['default']
def restriction(**kwargs): if not (settings.WL_RCPT_FOR_GREYLISTING or settings.WL_RCPT_WITHOUT_SPF): logger.debug( 'No setting available: WL_RCPT_FOR_GREYLISTING, WL_RCPT_WITHOUT_SPF. Skip.' ) return SMTP_ACTIONS['default'] sasl_username = kwargs['sasl_username'] if not sasl_username: logger.debug('No sasl_username found, skip.') return SMTP_ACTIONS['default'] recipient = kwargs['recipient'] if not is_email(recipient): logger.debug('Recipient is not a valid email address, skip.') return SMTP_ACTIONS['default'] # Check whether recipient domain is hosted locally. sasl_username_domain = kwargs['sasl_username_domain'] recipient_domain = kwargs['recipient_domain'] if sasl_username_domain == recipient_domain: logger.debug('Sender domain is same as recipient domain, skip.') return SMTP_ACTIONS['default'] conn_vmail = kwargs['conn_vmail'] if is_local_domain(conn=conn_vmail, domain=recipient_domain): logger.debug('Recipient domain is local domain, skip.') return SMTP_ACTIONS['default'] conn_iredapd = kwargs['conn_iredapd'] # Submit recipient as whitelisted sender directly if settings.WL_RCPT_WITHOUT_SPF: if settings.WL_RCPT_LOCAL_ACCOUNT == 'user': _wl_account = sasl_username elif settings.WL_RCPT_LOCAL_ACCOUNT == 'domain': _wl_account = sasl_username_domain else: _wl_account = '@.' if settings.WL_RCPT_RCPT == 'domain': _wl_sender = recipient_domain else: _wl_sender = recipient qr = lib_gl.add_whitelist_sender(conn=conn_iredapd, account=_wl_account, sender=_wl_sender) if qr[0]: logger.info('Recipient %s has been whitelisted for %s.' % (_wl_sender, _wl_account)) else: logger.error( '<!> Error while whitelisting recipient %s for %s: %s' % (_wl_sender, _wl_account, qr[1])) if settings.WL_RCPT_FOR_GREYLISTING: if settings.WL_RCPT_WHITELIST_DOMAIN_FOR_GREYLISTING: # Whitelist recipient domain for greylisting qr = lib_gl.add_whitelist_domain(conn=conn_iredapd, domain=recipient_domain) if qr[0]: logger.info( 'Domain %s has been whitelisted globally for greylisting service.' % recipient_domain) else: logger.error( '<!> Error while whitelisting domain %s globally for greylisting service: %s' % (recipient_domain, qr[1])) else: # Whitelist recipient for greylisting qr = lib_gl.add_whitelist_sender(conn=conn_iredapd, account=sasl_username, sender=recipient, comment='AUTO-WHITELISTED') if qr[0]: logger.info( 'Address %s has been whitelisted for greylisting service for local user %s.' % (recipient, sasl_username)) else: logger.error( '<!> Error while whitelisting address %s for greylisting service for local user %s: %s' % (recipient, sasl_username, qr[1])) return SMTP_ACTIONS['default']
def restriction(**kwargs): sasl_username = kwargs['sasl_username'] sasl_username_domain = kwargs['sasl_username_domain'] if not sasl_username: logger.debug('SKIP, not an email sent from an authenticated user (no sasl_username found).') return SMTP_ACTIONS['default'] try: size = int(kwargs['smtp_session_data']['size']) except Exception as e: logger.error('SKIP, cannot get mail message size. Error: %s' % repr(e)) return SMTP_ACTIONS['default'] policy_accounts = [sasl_username] + utils.get_policy_addresses_from_email(sasl_username) # Get db cursor conn_vmail = kwargs['conn_vmail'] if settings.backend == 'ldap': conn_relay = kwargs['conn_iredapd'] else: conn_relay = kwargs['conn_vmail'] recipient_domain = kwargs['recipient_domain'] if kwargs['smtp_session_data']['protocol_state'] == 'RCPT': if sasl_username_domain == recipient_domain: logger.debug('SASL username domain is same as recipient domain (%s), use default relay: %s' % (recipient_domain, relay_for_local_recipient)) return 'FILTER %s' % relay_for_local_recipient if is_local_domain(conn=conn_vmail, domain=recipient_domain, include_backupmx=True): logger.debug('Recipient domain (%s) is locally hosted, use default relay: %s' % (recipient_domain, relay_for_local_recipient)) return 'FILTER %s' % relay_for_local_recipient if kwargs['smtp_session_data']['protocol_state'] == 'END-OF-MESSAGE': logger.debug('Recipient domain (%s) is NOT locally hosted.' % relay_for_local_recipient) # Query sql db to get highest custom relayhost. sql = """ SELECT relayhost FROM custom_relay WHERE account IN %(accounts)s AND ((min_size = 0 AND max_size >= %(size)d) OR (min_size <= %(size)d AND max_size >= %(size)d) OR (min_size < %(size)d AND max_size = 0) OR (min_size = 0 AND max_size = 0)) ORDER BY priority ASC LIMIT 1 """ % {'size': size, 'accounts': sqlquote(policy_accounts)} logger.debug('[SQL] Query custom relayhost with highest priority: \n%s' % sql) try: qr = conn_relay.execute(sql) qr_relay = qr.fetchone()[0] logger.debug('[SQL] Query result: %s' % qr_relay) except Exception as e: logger.error('Error while querying custom relayhost (fallback to default action): %s' % repr(e)) return SMTP_ACTIONS['default'] if qr_relay: logger.debug('Return custom relayhost: %s' % qr_relay) return 'FILTER %s' % qr_relay else: logger.debug('No custom relayhost, return default action.') return SMTP_ACTIONS['default'] return SMTP_ACTIONS['default']