<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[9424] CalendarServer/trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.macosforge.org/projects/calendarserver/changeset/9424">9424</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2012-07-10 17:02:29 -0700 (Tue, 10 Jul 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Allow LDAP config to use multiple LDAP attributes for emailAddresses (so that both primary address and email aliases may be used for principal-property-search and faulting in individual records).</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunkconfcaldavdtestplist">CalendarServer/trunk/conf/caldavd-test.plist</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryldapdirectorypy">CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryprincipalpy">CalendarServer/trunk/twistedcaldav/directory/principal.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_ldapdirectorypy">CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavresourcepy">CalendarServer/trunk/twistedcaldav/resource.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavstdconfigpy">CalendarServer/trunk/twistedcaldav/stdconfig.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunkconfcaldavdtestplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/conf/caldavd-test.plist (9423 => 9424)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/conf/caldavd-test.plist        2012-07-10 22:57:46 UTC (rev 9423)
+++ CalendarServer/trunk/conf/caldavd-test.plist        2012-07-11 00:02:29 UTC (rev 9424)
</span><span class="lines">@@ -267,7 +267,9 @@
</span><span class="cx">               &lt;key&gt;fullName&lt;/key&gt;
</span><span class="cx">               &lt;string&gt;cn&lt;/string&gt;
</span><span class="cx">               &lt;key&gt;emailAddresses&lt;/key&gt;
</span><del>-              &lt;string&gt;mail&lt;/string&gt;
</del><ins>+              &lt;array&gt;
+                  &lt;string&gt;mail&lt;/string&gt;
+              &lt;/array&gt;
</ins><span class="cx">               &lt;key&gt;firstName&lt;/key&gt;
</span><span class="cx">               &lt;string&gt;givenName&lt;/string&gt;
</span><span class="cx">               &lt;key&gt;lastName&lt;/key&gt;
</span><span class="lines">@@ -291,7 +293,9 @@
</span><span class="cx">               &lt;key&gt;fullName&lt;/key&gt;
</span><span class="cx">               &lt;string&gt;cn&lt;/string&gt;
</span><span class="cx">               &lt;key&gt;emailAddresses&lt;/key&gt;
</span><del>-              &lt;string&gt;mail&lt;/string&gt;
</del><ins>+              &lt;array&gt;
+                  &lt;string&gt;mail&lt;/string&gt;
+              &lt;/array&gt;
</ins><span class="cx">               &lt;key&gt;firstName&lt;/key&gt;
</span><span class="cx">               &lt;string&gt;givenName&lt;/string&gt;
</span><span class="cx">               &lt;key&gt;lastName&lt;/key&gt;
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectoryldapdirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py (9423 => 9424)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py        2012-07-10 22:57:46 UTC (rev 9423)
+++ CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py        2012-07-11 00:02:29 UTC (rev 9424)
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx">                     &quot;mapping&quot; : { # maps internal record names to LDAP
</span><span class="cx">                         &quot;recordName&quot;: &quot;uid&quot;,
</span><span class="cx">                         &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                        &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                        &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
</ins><span class="cx">                         &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                         &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                     },
</span><span class="lines">@@ -131,7 +131,7 @@
</span><span class="cx">                     &quot;mapping&quot; : { # maps internal record names to LDAP
</span><span class="cx">                         &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                         &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                        &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                        &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
</ins><span class="cx">                         &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                         &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                     },
</span><span class="lines">@@ -146,7 +146,7 @@
</span><span class="cx">                     &quot;mapping&quot; : { # maps internal record names to LDAP
</span><span class="cx">                         &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                         &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                        &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                        &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
</ins><span class="cx">                         &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                         &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                     },
</span><span class="lines">@@ -161,7 +161,7 @@
</span><span class="cx">                     &quot;mapping&quot; : { # maps internal record names to LDAP
</span><span class="cx">                         &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                         &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                        &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                        &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
</ins><span class="cx">                         &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                         &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                     },
</span><span class="lines">@@ -235,9 +235,14 @@
</span><span class="cx">                 attrSet.add(self.rdnSchema[recordType][&quot;attr&quot;])
</span><span class="cx">             if self.rdnSchema[recordType].get(&quot;calendarEnabledAttr&quot;, False):
</span><span class="cx">                 attrSet.add(self.rdnSchema[recordType][&quot;calendarEnabledAttr&quot;])
</span><del>-            for attr in self.rdnSchema[recordType][&quot;mapping&quot;].values():
-                if attr:
-                    attrSet.add(attr)
</del><ins>+            for attrList in self.rdnSchema[recordType][&quot;mapping&quot;].values():
+                if attrList:
+                    # Since emailAddresses can map to multiple LDAP fields,
+                    # support either string or list
+                    if isinstance(attrList, str):
+                        attrList = [attrList]
+                    for attr in attrList:
+                        attrSet.add(attr)
</ins><span class="cx">             # Also put the guidAttr attribute into the mappings for each type
</span><span class="cx">             # so recordsMatchingFields can query on guid
</span><span class="cx">             self.rdnSchema[recordType][&quot;mapping&quot;][&quot;guid&quot;] = self.rdnSchema[&quot;guidAttr&quot;]
</span><span class="lines">@@ -646,9 +651,10 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         results = []
</span><span class="cx">         for key in keys:
</span><del>-            values = attrs.get(key)
-            if values is not None:
-                results += values
</del><ins>+            if key:
+                values = attrs.get(key)
+                if values is not None:
+                    results += values
</ins><span class="cx">         return results
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -686,7 +692,13 @@
</span><span class="cx">                 raise MissingGuidException()
</span><span class="cx"> 
</span><span class="cx">         # Find or build email
</span><del>-        emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType][&quot;mapping&quot;][&quot;emailAddresses&quot;]))
</del><ins>+        # (The emailAddresses mapping is a list of ldap fields)
+        emailAddressesMappedTo = self.rdnSchema[recordType][&quot;mapping&quot;][&quot;emailAddresses&quot;]
+        # Supporting either string or list for emailAddresses:
+        if isinstance(emailAddressesMappedTo, str):
+            emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType][&quot;mapping&quot;][&quot;emailAddresses&quot;]))
+        else:
+            emailAddresses = set(self._getMultipleLdapAttributes(attrs, *self.rdnSchema[recordType][&quot;mapping&quot;][&quot;emailAddresses&quot;]))
</ins><span class="cx">         emailSuffix = self.rdnSchema[recordType][&quot;emailSuffix&quot;]
</span><span class="cx"> 
</span><span class="cx">         if len(emailAddresses) == 0 and emailSuffix:
</span><span class="lines">@@ -885,7 +897,16 @@
</span><span class="cx">                         ldapEsc(email)
</span><span class="cx">                     )
</span><span class="cx">                 else:
</span><del>-                    filterstr = &quot;(&amp;%s(mail=%s))&quot; % (filterstr, ldapEsc(email))
</del><ins>+                    # emailAddresses can map to multiple LDAP fields
+                    ldapFields = self.rdnSchema[recordType][&quot;mapping&quot;][&quot;emailAddresses&quot;]
+                    if isinstance(ldapFields, str):
+                        subfilter = &quot;(%s=%s)&quot; % (ldapFields, ldapEsc(email))
+                    else:
+                        subfilter = []
+                        for ldapField in ldapFields:
+                            subfilter.append(&quot;(%s=%s)&quot; % (ldapField, ldapEsc(email)))
+                        subfilter = &quot;(|%s)&quot; % (&quot;&quot;.join(subfilter))
+                    filterstr = &quot;(&amp;%s%s)&quot; % (filterstr, subfilter)
</ins><span class="cx"> 
</span><span class="cx">             elif indexType == self.INDEX_TYPE_AUTHID:
</span><span class="cx">                 return
</span><span class="lines">@@ -1157,7 +1178,13 @@
</span><span class="cx">         if ldapField:
</span><span class="cx">             combined.setdefault(field, []).append((value, caseless, matchType))
</span><span class="cx">             value = _convertValue(value, matchType)
</span><del>-            converted.append(&quot;(%s=%s)&quot; % (ldapField, value))
</del><ins>+            if isinstance(ldapField, str):
+                converted.append(&quot;(%s=%s)&quot; % (ldapField, value))
+            else:
+                subConverted = []
+                for lf in ldapField:
+                    subConverted.append(&quot;(%s=%s)&quot; % (lf, value))
+                converted.append(&quot;(|%s)&quot; % &quot;&quot;.join(subConverted))
</ins><span class="cx"> 
</span><span class="cx">     if len(converted) == 0:
</span><span class="cx">         return None
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectoryprincipalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py (9423 => 9424)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/principal.py        2012-07-10 22:57:46 UTC (rev 9423)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py        2012-07-11 00:02:29 UTC (rev 9424)
</span><span class="lines">@@ -631,7 +631,7 @@
</span><span class="cx">         if record.enabledForCalendaring:
</span><span class="cx">             return tag.fillSlots(
</span><span class="cx">                 calendarUserAddresses=formatLinks(
</span><del>-                    resource.calendarUserAddresses()
</del><ins>+                    sorted(resource.calendarUserAddresses())
</ins><span class="cx">                 ),
</span><span class="cx">                 calendarHomes=formatLinks(resource.calendarHomeURLs())
</span><span class="cx">             )
</span><span class="lines">@@ -755,7 +755,7 @@
</span><span class="cx"> 
</span><span class="cx">             elif name == &quot;email-address-set&quot;:
</span><span class="cx">                 returnValue(customxml.EmailAddressSet(
</span><del>-                    *[customxml.EmailAddressProperty(addr) for addr in self.record.emailAddresses]
</del><ins>+                    *[customxml.EmailAddressProperty(addr) for addr in sorted(self.record.emailAddresses)]
</ins><span class="cx">                 ))
</span><span class="cx"> 
</span><span class="cx">         result = (yield super(DirectoryPrincipalResource, self).readProperty(property, request))
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_ldapdirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py (9423 => 9424)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py        2012-07-10 22:57:46 UTC (rev 9423)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py        2012-07-11 00:02:29 UTC (rev 9424)
</span><span class="lines">@@ -410,7 +410,7 @@
</span><span class="cx">                         &quot;mapping&quot;: { # maps internal record names to LDAP
</span><span class="cx">                             &quot;recordName&quot;: &quot;uid&quot;,
</span><span class="cx">                             &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                            &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                            &quot;emailAddresses&quot; : [&quot;mail&quot;, &quot;emailAliases&quot;],
</ins><span class="cx">                             &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                             &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                         },
</span><span class="lines">@@ -423,7 +423,7 @@
</span><span class="cx">                         &quot;mapping&quot;: { # maps internal record names to LDAP
</span><span class="cx">                             &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                             &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                            &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                            &quot;emailAddresses&quot; : [&quot;mail&quot;, &quot;emailAliases&quot;],
</ins><span class="cx">                             &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                             &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                         },
</span><span class="lines">@@ -438,7 +438,7 @@
</span><span class="cx">                         &quot;mapping&quot;: { # maps internal record names to LDAP
</span><span class="cx">                             &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                             &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                            &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                            &quot;emailAddresses&quot; : [&quot;mail&quot;, &quot;emailAliases&quot;],
</ins><span class="cx">                             &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                             &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                         },
</span><span class="lines">@@ -453,7 +453,7 @@
</span><span class="cx">                         &quot;mapping&quot;: { # maps internal record names to LDAP
</span><span class="cx">                             &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                             &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                            &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                            &quot;emailAddresses&quot; : [&quot;mail&quot;, &quot;emailAliases&quot;],
</ins><span class="cx">                             &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                             &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                         },
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/resource.py (9423 => 9424)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/resource.py        2012-07-10 22:57:46 UTC (rev 9423)
+++ CalendarServer/trunk/twistedcaldav/resource.py        2012-07-11 00:02:29 UTC (rev 9424)
</span><span class="lines">@@ -1908,7 +1908,7 @@
</span><span class="cx"> 
</span><span class="cx">             elif name == &quot;calendar-user-address-set&quot;:
</span><span class="cx">                 returnValue(caldavxml.CalendarUserAddressSet(
</span><del>-                    *[element.HRef(uri) for uri in self.calendarUserAddresses()]
</del><ins>+                    *[element.HRef(uri) for uri in sorted(self.calendarUserAddresses())]
</ins><span class="cx">                 ))
</span><span class="cx"> 
</span><span class="cx">             elif name == &quot;schedule-inbox-URL&quot;:
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavstdconfigpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py (9423 => 9424)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/stdconfig.py        2012-07-10 22:57:46 UTC (rev 9423)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py        2012-07-11 00:02:29 UTC (rev 9424)
</span><span class="lines">@@ -97,7 +97,7 @@
</span><span class="cx">                 &quot;mapping&quot; : { # maps internal record names to LDAP
</span><span class="cx">                     &quot;recordName&quot;: &quot;uid&quot;,
</span><span class="cx">                     &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                    &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                    &quot;emailAddresses&quot; : [&quot;mail&quot;],
</ins><span class="cx">                     &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                     &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                 },
</span><span class="lines">@@ -110,7 +110,7 @@
</span><span class="cx">                 &quot;mapping&quot; : { # maps internal record names to LDAP
</span><span class="cx">                     &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                     &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                    &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                    &quot;emailAddresses&quot; : [&quot;mail&quot;],
</ins><span class="cx">                     &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                     &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                 },
</span><span class="lines">@@ -125,7 +125,7 @@
</span><span class="cx">                 &quot;mapping&quot; : { # maps internal record names to LDAP
</span><span class="cx">                     &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                     &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                    &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                    &quot;emailAddresses&quot; : [&quot;mail&quot;],
</ins><span class="cx">                     &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                     &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                 },
</span><span class="lines">@@ -140,7 +140,7 @@
</span><span class="cx">                 &quot;mapping&quot; : { # maps internal record names to LDAP
</span><span class="cx">                     &quot;recordName&quot;: &quot;cn&quot;,
</span><span class="cx">                     &quot;fullName&quot; : &quot;cn&quot;,
</span><del>-                    &quot;emailAddresses&quot; : &quot;mail&quot;,
</del><ins>+                    &quot;emailAddresses&quot; : [&quot;mail&quot;],
</ins><span class="cx">                     &quot;firstName&quot; : &quot;givenName&quot;,
</span><span class="cx">                     &quot;lastName&quot; : &quot;sn&quot;,
</span><span class="cx">                 },
</span></span></pre>
</div>
</div>

</body>
</html>