示例#1
0
    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
示例#2
0
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"]
示例#3
0
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
示例#4
0
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']
示例#6
0
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']