Yalo
    e-mail
    internet accelerators
    internet access
    internet and phone call
    web hosting
    storage space
    url redirection
    internet call waiting
    free sms
    nota bene
 
 

How to enforce per-domain quota AND per-user quota in Dovecot mail server

  • Requisites: Dovecot 2.0.7, Postfix 2.7.1, Postfix Admin 2.3.2, MySQL server
  • Postfix configuration

    From Postfix main.conf file

    # Use dovecot-lmtp to deliver messages in mail boxes or maildirs
    virtual_transport = lmtp:unix:private/dovecot-lmtp
    
  • Dovecot configuration

    Only quota relevant lines are shown from Dovecot configuration.

    From dovecot.conf file

    
    # User accounts data are in MySQL database
    #
    userdb {
      driver = sql
      args = /etc/dovecot/dovecot-mysql.conf
    }
    
    # Use quota plugin
    mail_plugins = $mail_plugins quota
    
    protocol imap {
      # Space separated list of plugins to load (default is global mail_plugins).
      mail_plugins = $mail_plugins imap_quota
    }
    
    # Use dictionary service for quota
    service dict {
      unix_listener dict {
        mode = 0660
        group = dovecot
      }
    }
    
    
    plugin {
    
    ## One dictionary quota to track and enforce domains quotas
    quota = dict:Domain quota:%d:proxy::quota_domain
    ##
    ## Another dict quota to track only users quotas 
    quota2 = dict:User quota::proxy::quota_user
    ##
    ## And finally a maildirsize quota to enforce (and track) users quotas
    quota3 = maildir
    
    }
    
    ## Dictionary quotas are held in MySQL database. 
    dict {
     quota_user = mysql:/etc/dovecot/dovecot-dict-mysql.conf
     quota_domain = mysql:/etc/dovecot/dovecot-dict-mysql-domain.conf
    }
    

    You may list more quota root definitions appending an increasing number to word quota: quota2, quota3, etc. But one dictionary quota can be enforced at a time only. Dict quota to be enforced (either user or domain quota) MUST be defined as quota = without any number and has to be the single one. If there are multiple quota = lines without number only the last one will be active. That quota definition line must match also with only one active user_query defined in the dovecot-mysql.conf file. Maildirsize quota can be applied to users but not to domains. Taken in consideration all that said we define three quotas root to accomplish our goal.

    The dovecot-dict-mysql.conf file

    connect = host=host_name dbname=db_name user=user_name password=pass_word
    
    map {
      pattern = priv/quota/storage
      table = quota2
      username_field = username
      value_field = bytes
    }
    
    map {
      pattern = priv/quota/messages
      table = quota2
      username_field = username
      value_field = messages
    }
    

    The dovecot-dict-mysql-domain.conf file

    connect = host=host_name dbname=db_name user=user_name password=pass_word
    
    map {
      pattern = priv/quota/storage
      table = domain
      username_field = domain
      value_field = quota
    }
    
    map {
      pattern = priv/quota/messages
      table = quota2
      username_field = username
      value_field = messages
    }
    

    From dovecot-mysql.conf file

    ## user_query EXAMPLE with user quota enforcement
    ##
    user_query = SELECT concat('/wrk/vmail/', maildir) AS home, CONCAT('*:bytes=', quota) AS quota_rule FROM mailbox 
    WHERE username = '%u' AND mailbox.active = '1'
    
    ## user_query EXAMPLE with domain quota enforcement
    ## PostfixAdmin apparently has a bug, it saves user quotas in bytes but domain quota in Megabytes
    ## You can fix PostfixAdmin code or introduce a multiplier (*1024000) in SQL query, like it is shown
    ##
    #user_query = SELECT concat('/wrk/vmail/', maildir) AS home, CONCAT('*:bytes=', maxquota*1024000) AS quota_rule 
    FROM mailbox, domain WHERE username = '%u' AND mailbox.active = '1' AND domain.domain = '%d' AND domain.active = '1'
    
    ## Use ONE user_query ONLY
    ## You can enforce ONE dictionary quota at a time ONLY, either user quota OR domain quota
    ## If you leave uncommented more than one user_query last one will be active
    
  • PostfixAdmin bug editting

    In edit-domain.php file find $tMaxquota = $domain_properties['maxquota'];
    and replace it with $tMaxquota = divide_quota($domain_properties['maxquota']);

    Find $fMaxquota = intval($_POST['fMaxquota']);
    and replace it with $fMaxquota = multiply_quota(intval($_POST['fMaxquota']));

    In templates/admin_list-domain.php find print $domain_properties[$i]['maxquota'];
    and replace it with print divide_quota($domain_properties[$i]['maxquota']);

    If you fixed PostfixAdmin bug then use this user_query template without a multiplier

    user_query = SELECT concat('/wrk/vmail/', maildir) AS home, CONCAT('*:bytes=', maxquota) AS quota_rule 
    FROM mailbox, domain WHERE username = '%u' AND mailbox.active = '1' AND domain.domain = '%d' AND domain.active = '1'
    
  • The maildirsize file

    If does not exist Dovecot will create new maildirsize file with zero quota limit. To actually enforce user quota you have to initialize somehow maildirsize file with some non zero value. Format is <quota limit in bytes>S, for example

    1024S
    1024000S
    1024000000S

    for 1 Kbyte, 1 Mbyte and 1 Gbyte respectively