The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Mail::Decency::Policy::Throttle

DESCRIPTION

Throtle mail sending for dedicated sources (sender ip, sender username, sender address, "account")

  • client address

    The IP of the client connecting to the server.

  • sender username, sender domain, sender address

    The username is the (if any provided) sasl username

  • recipient domain, recipient address

    Caution with this. You don't want your incoming mails to be rejected!

  • account

    An account is a kind of context. You can associate each row in the database with an column called "account". The counter for throtteling will then be applied to this value instead of sender or such.

    Example usecase: There are domain1.tld and domain2.tld. The task is to limit the max amount for sending to 500 Mails per day for both domains together.

CONFIG

Those are the config params in YAML

    ---
    
    disable: 0
    
    # Wheter affect ONLY those having a sasl username set.
    #   Use this if you have one mailserver for incoming AND outgoing
    #   mails. This does not check the validity of the sasl user!
    require_sasl_username: 1
    
    # Wheter use the counters generated by the Mail::Decency::LogParser::Stats
    #   module which has to be up and running.
    #   Your limits might be a little streched, depending on the speed of
    #   the log parser (+1 or +2 or something).
    #   However, this is the only way to assure only not-rejected mails
    #   get accounted for.
    #   If disabled, ANY mail seen will increment the counter (if a later
    #   configuration setting does reject it, it still counts!)
    use_stats_cache: 0
    
    # The default limits, if no exception is in the exception database.
    #   You can use:
    #       * client_address (ip of sending client)
    #       * sender_domain (domain part of sender)
    #       * sender_address (email address of sender)
    #       * sasl_username (the sasl username, if any)
    #       * sender_domain (domain part of sender)
    #       * recipient_domain (domain part of the recipient)
    #       * recipient_address (email address of recipient)
    #       * account (the account.. see above)
    default_limits:
        
        # the following can be read as:
        #   * Account per sender domain
        #   * It is not allowed to send more then:
        #       * 1 Mail per 10 Seconds
        #       * 50 Mails per 10 Minutes
        #       * 1000 Mails per day
        sender_domain:
            -
                maximum: 1
                interval: 10
            -
                maximum: 50
                interval: 600
            -
                maximum: 1000
                interval: 86400
        account:
            -
                maximum: 50
                interval: 600
    
    # which exception database to use (see above)
    #   use only those you really have to. Don't activate all
    #   without actually having data!
    exception_databases:
        - sender_domain
        - sender_address
    
    # The reject messages per interval (above)
    #   Don't forget the rejection code (better use 4xx for
    #   temporary, instead of 5xx for hard)
    reject_messages:
        10:
            message: 'Sorry, nicht mehr als eine Mail in 10 Sekunden'
            code: 450
        600:
            message: 'Sorry, nicht mehr als 50 Mails in 10 Minuten'
            code: 450
        86400:
            message: 'Sorry, nicht mehr als 1000 Mails pro Tag'
            code: 450
    
    # The default error message which will be used if none is set
    #   for the interval.. comes in handy if you use exception 
    #   database with custom intervals
    #   Variables you can use are:
    #       * %maximum% (limit of mails in interval)
    #       * %interval% (interval in seconds)
    #       * %interval_minutes% (interval in minutes, round up)
    #       * %interval_hours% (interval in hours, round up)
    #       * %interval_days% (interval in days, round up)
    default_reject_message:
        message: 'Sorry, nicht mehr als %maximum% Mails in %interval_minutes% Minuten'
        code: 450
    

DATABASE

    CREATE TABLE throttle_client_address (
        id INTEGER PRIMARY KEY,
        client_address VARCHAR( 255 ),
        interval INTEGER,
        maximum INTEGER,
        account VARCHAR( 25 )
    );
    CREATE UNIQUE INDEX throttle_client_address_uk ON throttle_client_address( client_address, interval );
    
    CREATE TABLE throttle_sender_domain (
        id INTEGER PRIMARY KEY,
        sender_domain VARCHAR( 255 ),
        interval INTEGER,
        maximum INTEGER,
        account VARCHAR( 25 )
    );
    CREATE UNIQUE INDEX throttle_sender_domain_uk ON throttle_sender_domain( sender_domain, interval );
    
    CREATE TABLE throttle_sender_address(
        id INTEGER PRIMARY KEY,
        sender_address VARCHAR( 255 ),
        interval INTEGER,
        maximum INTEGER,
        account VARCHAR( 25 )
    );
    CREATE UNIQUE INDEX throttle_sender_address_uk ON throttle_sender_address( sender_address, interval );
    
    CREATE TABLE throttle_sasl_username(
        id INTEGER PRIMARY KEY,
        sasl_username VARCHAR( 255 ),
        interval INTEGER,
        maximum INTEGER,
        account VARCHAR( 25 )
    );
    CREATE UNIQUE INDEX throttle_sasl_username_uk ON throttle_sasl_username( sasl_username, interval );
    
    CREATE TABLE throttle_recipient_domain(
        id INTEGER PRIMARY KEY,
        recipient_domain VARCHAR( 255 ),
        interval INTEGER,
        maximum INTEGER,
        account VARCHAR( 25 )
    );
    CREATE UNIQUE INDEX throttle_recipient_domain_uk ON throttle_recipient_domain( recipient_domain, interval );
    
    CREATE TABLE throttle_recipient_address(
        id INTEGER PRIMARY KEY,
        recipient_address VARCHAR( 255 ),
        interval INTEGER,
        maximum INTEGER,
        account VARCHAR( 25 )
    );
    CREATE UNIQUE INDEX throttle_recipient_address_uk ON throttle_recipient_address( recipient_address, interval );
    
    CREATE TABLE throttle_account(
        id INTEGER PRIMARY KEY,
        account VARCHAR( 255 ),
        interval INTEGER,
        maximum INTEGER
    );
    CREATE UNIQUE INDEX throttle_account_uk ON throttle_account( account, interval );

CLASS ATTRIBUTES

default_reject_message : HashRef

Defauilt reject message and default reject code

    {
        message => 'Sorry, Limit reached (%maximum% mails in %interval% seconds)',
        code    => 450
    }

reject_messages : HashRef[HashRef]

Reject messages per interval

    {
        10 => {
            message => 'Sorry, Limit reached .. not more then 99 in 10 seconds',
            code    => 450
        },
        86400 => {
            message => 'Sorry, Limit reached .. not more then 101 in 24 hours',
            code    => 450
        }
    }

default_limits : HashRef

Limits per attribute ( sender_domain, client_address, recipient_domain, account, .. )

    {
        sender_domain => [
            {
                maximum => 99,
                interval => 10,
            }
        ],
    }

default_limit_databases : ArrayRef[HashRef]

Which limit databases .. internal usage

exception_database : HashRef

Exception from default values (eg per account, per sender_domain, whatever)

used_databases : ArrayRef[Str]

Internal usage..

use_accounts : Bool

Wheter accounts (see description) should be used or not (cost performance)

counter_increment : CodeRef

Internal usage..

counter_read : CodeRef

Internal usage..

require_sasl_username : CodeRef

Enable throttle module only if sasl_username is given (this happens if the SMTP connection contains AUTH information.. )

schema_definition

Database ..

METHODS

init

handle

get_account $db, $value

returns account by attribute lookup

    my $account = $self->get_account( sender_domain => 'sender.tld' );

AUTHOR

Ulrich Kautz <uk@fortrabbit.de>

COPYRIGHT

Copyright (c) 2010 the "AUTHOR" as listed above

LICENCSE

This library is free software and may be distributed under the same terms as perl itself.