Internal mail lists not working

Issue #792 open
Martin Nadvornik created an issue

Hi,

I've got a problem getting our internal mailling lists to work. I have just configured LDAP to our iredmail server. When logged in as a user I can see mail received or sent without problem. The only mails which are not appearing in search are mails sent directly to a mailing list the user is member of. When beeing logged in as auditor I am able to see the mail which must mean it is indexed.

I have set the following parameters for ldap:

$config['ENABLE_LDAP_AUTH'] = 1;
$config['LDAP_HOST'] = 'some ip';
$config['LDAP_HELPER_DN'] = 'cn=manager,dc=domain,dc=at';
$config['LDAP_HELPER_PASSWORD'] = '';
$config['LDAP_MAIL_ATTR'] = 'mail';
$config['LDAP_AUDITOR_MEMBER_DN'] = '';
$config['LDAP_ADMIN_MEMBER_DN'] = '';
$config['LDAP_ACCOUNT_OBJECTCLASS'] = 'mailUser';
$config['LDAP_BASE_DN'] = 'o=domains,dc=domain,dc=at';
$config['LDAP_DISTRIBUTIONLIST_OBJECTCLASS'] = 'mailList';
$config['LDAP_DISTRIBUTIONLIST_ATTR'] = 'memberOfGroup';
$config['LDAP_MAIL_ATTR'] = 'mail';

Excerpt from our LDAP:

# it@domain.at, Groups, domain.at, domains, domain.at
dn: mail=redacted@domain.at,ou=Groups,domainName=domain.at,o=domains,dc=domain,dc=at
objectClass: mailList
mail: it@domain.at
enabledService: mail
enabledService: deliver
enabledService: displayedInGlobalAddressBook
accessPolicy: public
cn: it
accountStatus: active
hasMember: yes

# redacted.redacted@domain.at, Users, domain.at, domains, domain.at
dn: mail=redacted.redacted@domain.at,ou=Users,domainName=domain.at,o=domains,dc=domain,dc=at
objectClass: inetOrgPerson
objectClass: shadowAccount
objectClass: amavisAccount
objectClass: mailUser
objectClass: top
storageBaseDirectory: /var/vmail/vmail1
mail: redacted.redacted@domain.at
uid: redacted.redacted
cn: redacted redacted
givenName: Martin
sn: Nadvornik
mailQuota: 4294967296
accountStatus: active
memberOfGroup: redacted@domain.at
memberOfGroup: redacted@domain.at

Is there any way to debug why only the mailling lists do not work for me?

Comments (9)

  1. Janos SUTO repo owner

    Yes, there is. Locate model/user/auth.php, and find the function called checkLoginAgainstLDAP_real(). This should find all email addresses for the given user. I suggest to check the ldap query itself as well as the results it returns.

  2. Martin Nadvornik reporter

    Hi Janos,

    I think I found the bug. I believe it is a bug in your auth.php->get_email_array_from_ldap_attr() function.

    First I turned on debugging and found the following ldap query in syslog:

    ldap query: base dn='o=domains,dc=domain,dc=at', filter='(|(&(objectClass=mailUser)(mail=someone.someone@domain.at))(&(objectClass=mailList)(memberOfGroup=someone.someone@domain.at))(&(objectClass=mailList)(memberOfGroup=mail=someone.someone@domain.at,ou=Users,domainName=domain.at,o=domains,dc=domain,dc=at)))', attr='', 1 hits
    

    When doing a manual ldapsearch with the above filter I do see attributes like

    memberOfGroup: list1@domain.at
    memberOfGroup: list2@domain.at
    memberOfGroup: list3@domain.at
    

    When looking at the $query->rows variable which is passed over as the parameter for the get_email_array_from_ldap_attr($e = array()) function, it looks as follows:

    array(1) {
      [0]=>
      array(16) {
        ["objectclass"]=>
        array(6) {
          ["count"]=>
          int(5)
          [0]=>
          string(13) "inetOrgPerson"
          [1]=>
          string(13) "shadowAccount"
          [2]=>
          string(13) "amavisAccount"
          [3]=>
          string(8) "mailUser"
          [4]=>
          string(3) "top"
        }
        ["memberofgroup"]=>
        array(7) {
          ["count"]=>
          int(6)
          [0]=>
          string(15) "list1@domain.at"
          [1]=>
          string(14) "list2@domain.at"
          [2]=>
          string(20) "list3@domain.at"
          [3]=>
          string(28) "list4@domain.at"
          [4]=>
          string(28) "list5@domain.at"
          [5]=>
          string(29) "list6@domain.at"
        }
        ["dn"]=>
        string(93) "mail=someone.someone@domain.at,ou=Users,domainName=domain.at,o=domains,dc=domain,dc=at"
      }
    }
    

    The bug seems to be in the following foreach loop:

    foreach (array("mail", "mailalternateaddress", "proxyaddresses", "zimbraMailForwardingAddress", "member", "memberOfGroup") as $mailattr) {
    

    You can see, that in the loop you are looking for the attribute "memberOfGroup". But the problem is in the $query->rows variable because the attribute is in lowercase there. I am not sure if this is a php ldap bug or something in your code as the ldapsearch returns the atrribute with correct uppercase but the php ldap query does not.

    My final fix was to change the string "memberOfGroup" to "memberofgroup" in the array of the foreach $mailattr loop. I hope you can find a good permanent fix for this.

    Thanks for your help!

  3. Janos SUTO repo owner

    Nice job. However, the fix is probably simpler than that. Fix the LDAP_DISTRIBUTIONLIST_ATTR variable in config-site.php, and you are done :

    $config['LDAP_DISTRIBUTIONLIST_ATTR'] = 'memberofgroup';
    
  4. Martin Nadvornik reporter
    • changed status to open

    Hi Janos,

    sorry to reopen this issue, but I still have a problem with getting distribution lists (and alias) to work with our iRedMail Server.

    Like I wrote at the beginning of this issue I "hacked" the auth.php and changed memberOfGroup to ``"memberofgroupin order to get distribution lists to work. My hack has been in place until we upgraded piler a while ago and we never noticed that it does not work anymore until now. I never tried settingLDAP_DISTRIBUTIONLIST_ATTR``` as you suggested in your last comment. However changing the setting has no effect for my issue.

    Like I already wrote, I still think this is a bug with the get_email_array_from_ldap_attr function.

    In auth.php you have the function checkLoginAgainstLDAP_real. Within there you query the ldap server with the code

    $query = $ldap->query($ldap_base_dn, "(|(&(objectClass=$ldap_account_objectclass)($ldap_mail_attr=$username_prefix$username))(&(objectClass=$ldap_distributionlist_objectclass)($ldap_distributionlist_attr=$username_pref    ix$username)" . ")(&(objectClass=$ldap_distributionlist_objectclass)($ldap_distributionlist_attr=" . $a['dn'] . ")))", array());
    

    The $emails variable ist set using this code as far as I can see

    $emails = $this->get_email_array_from_ldap_attr($query->rows);
    
    $extra_emails = $this->model_user_user->get_email_addresses_from_groups($emails);
    $emails = array_merge($emails, $extra_emails);
    

    And here lies the problem. Inside of get_email_array_from_ldap_attr you only have this foreach loop with hardcoded LDAP attributes:

    foreach (array("mail", "mailalternateaddress", "proxyaddresses", "zimbraMailForwardingAddress", "member", "memberOfGroup") as $mailattr) {
    

    This leads to the problem that none of the LDAP attributes set within the config file are respected. For example: When I set $config['LDAP_MAIL_ATTR'] = 'test'; within config-site.php I can still login and have permission for the correct address although there is no attribute called test. It just works because the attribute mail is hardcoded. If I would use a different mail server with a different attribute name I guess that I wouldn't be able to configure piler correctly. To me this seems to be a bug.

    With iRedMail (v0.9.5-1, not sure how the current stable version behaves) there are two places where distribution list members can be located

    1. Within attribute memberOfGroup in an object of objectClass mailList. This is the case if a mail list is part in another mail list
    2. Within attribute memberOfGroup in an object of objectClass mailUser. This is the case if a normal mail account is member of a mail list.

    In my point of view it would be best if the hardcoded attributes within get_email_array_from_ldap_attr would be freely configurable or additionally based on the configured _attr variables. A downside of the hardcoded attributes is also that access alias addresses is also not possible with iRedMail without a custom function because it is saved within the attribute `shadowAddress. I do know of course that I could solve this issue using custom authentication. But it seems redundant for me to write an extra function for something that is already implemented but not configurable.

    If you need any further information please let me know. Thanks, Martin

  5. Janos SUTO repo owner

    Hello Martin. The LDAP_MAIL_ATTR value is not used for logging in, because there’s a previous ldap connect with your credentials.

    This attribute matters however when you want to collect your email addresses. Probably I’d take the items in the foreach loop and perform a case insensitive comparison. That way memberofgroup would be recognized. Do you think this should work?

  6. Martin Nadvornik reporter

    Hello Janos, maybe I am understanding this wrong. Let’s say I have the address of my mail account users in LDAP within the attribute useraddress. If I set LDAP_MAIL_ATTR to useraddress it will be used in the ldap queries in line 219 and 232 in auth.php (version 1.3.7) as far as I can see. However it will be discarded in the foreach loop because useraddress is not part of the string array used in the loop. If there would be a query result that contains useraddress, the array would be passed to get_email_array_from_ldap_attr . In that function let’s look at $a. It contains a single entry from the query results. The next step is the foreach loop. For every entry of that string array the loop is executed once. So the loop code is executed 7 times. Every time $mailattr is set to one of the hardcoded attributes of the string array. The first thing within the loop code is always the if(isset($a[$mailattr])) . This means that if the address of the user was to be located in $a["useraddress"], the if statement would always be false. Since there is no else to that if statement the variable $email is also never sett

    This would mean to me that LDAP_MAIL_ATTR doesn’t have any effect and it is not possible to use a mailserver with attribute names that are not one of the hardcoded ones within that foreach loop. Am I missing something?

    Making the comparison case insensitive should of course work. That's essentially what I tried when I just replaced memberOfGroup with memberofgroup. However I think that this could lead to some unexpected problems. When I changed the comparison in the foreach loop a few days ago on our production server it initially worked without problems for the test accounts I tested with. However I got complaints a day later from some users that they were only shown a single or no e-mail. I already started investigating but have not come to a conclusion yet to why this happened. In the user settings page of the webinterface the users were shown their own address and all addresses of the distribution lists that they are part of. But when they where using the search they were shown only a single mail or none even if they executed an “empty” search that should just return every mail. It seems to me that the sphix query was not formed correctly for these affected users. It also appeared to me that it only happened if they were part of a large amount of distribution lists. All effected users had access to more than 10 addresses.

    This means changing the comparison to lower case could reveal a bug. It might of course just be a weird configuration issue on my side.

  7. Log in to comment