diff --git a/ldap_servers/LdapServer.class.php b/ldap_servers/LdapServer.class.php
index 1e339d4..1e86384 100644
--- a/ldap_servers/LdapServer.class.php
+++ b/ldap_servers/LdapServer.class.php
@@ -913,6 +913,28 @@ class LdapServer {
     }
   }
 
+  /**
+   * Util function to fetch an attribute value from an ldap entry
+   *
+   * @param array $ldap_entry
+   *   LDAP User entry array
+   * @param string $attribute
+   *   The attribute to fetch
+   * @param int $delta
+   *   The delta of the attribute to fetch.
+   *
+   * @return mixed
+   *   The attribute value or FALSE if not found
+  */
+  public function getAttributeValue($ldap_entry, $attribute, $delta = 0) {
+    if (!empty($ldap_entry['attr'][$attribute][$delta]) &&
+      // Get the value.
+      ($value = $ldap_entry['attr'][$attribute][$delta])) {
+      // Note we still return array values - caller can handle extraction.
+      return $value;
+    }
+    return FALSE;
+  }
 
 
   /**
diff --git a/ldap_user/LdapUserConf.class.php b/ldap_user/LdapUserConf.class.php
index d6be8ed..eb372a7 100644
--- a/ldap_user/LdapUserConf.class.php
+++ b/ldap_user/LdapUserConf.class.php
@@ -57,6 +57,49 @@ class LdapUserConf {
     'wsActions',
   );
 
+  /**
+   * Util to fetch mappings for a given server id
+   *
+   * @param string $sid
+   *   The server id
+   *
+   * @return array/bool
+   *   Array of mappings or FALSE if none found
+  */
+  private function getSynchMappings($sid) {
+    if (!empty($this->ldapUserSynchMappings[$sid]) &&
+        ($mappings = $this->ldapUserSynchMappings[$sid]) &&
+        is_array($mappings)) {
+      return $mappings;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Util to fetch attributes required for this user conf.
+   *
+   * @param int $synch_context
+   *   Any valid sync context constant.
+  */
+  public function getRequiredAttributes($synch_context) {
+    // Get the enabled servers.
+    $sids = array_filter(array_values($this->sids));
+    // Initialize our array.
+    $attributes = array() ;
+    // Loop over each server and fetch the mappings required.
+    foreach ($sids as $sid) {
+      if (($mappings = $this->getSynchMappings($sid))) {
+        foreach ($mappings as $detail) {
+          // Make sure the mapping is relevant to this context.
+          if (in_array($synch_context, $detail['contexts'])) {
+            // Add the attribute to our array.
+            $attributes[] = $detail['ldap_source'];
+          }
+        }
+      }
+    }
+    return $attributes;
+  }
 
   /**
    * @return boolean if any ldap servers are available for ldap user
@@ -525,14 +568,14 @@ class LdapUserConf {
    * @param array ldap entry $user_ldap_entry
    * @param object $ldap_server
    * @param array $edit see hook_user_save, hook_user_update, etc
-   * @param drupal account object $account
+   * @param int $synch_context
+   *   The synch context (see ldap_user.module)
    * @param string $op see hook_ldap_attributes_needed_alter
    */
 
   function entryToUserEdit($ldap_user, $ldap_server, &$edit, $synch_context, $op) {
     // need array of user fields and which direction and when they should be synched.
    // dpm('entryToUserEdit'); dpm($ldap_server);
-
     $synch_email = $this->isSynched('property.mail', $ldap_server, $synch_context, LDAP_USER_SYNCH_DIRECTION_TO_DRUPAL_USER);
   //  debug("entryToUserEdit isSynched property.mail synch_context=$synch_context, issynched=$synch_email");
     if ($synch_email && !isset($edit['mail'])) {
@@ -546,7 +589,6 @@ class LdapUserConf {
     else {
       $edit['mail'] = NULL;
     }
-
   //  debug('edit'); debug($edit);
 
     if ($this->isSynched('property.name', $ldap_server, $synch_context, LDAP_USER_SYNCH_DIRECTION_TO_DRUPAL_USER) && !isset($edit['name'])) {
@@ -591,14 +633,46 @@ class LdapUserConf {
       $edit['ldap_user_current_dn'][LANGUAGE_NONE][0]['value'] = $ldap_user['dn'];
     }
 
-
-        /**
-     * @todo
-     * -- loop through all mapped entries AND invoke hook to get them all (or both)
-     */
-
-  //  dpm('post-entryToUserEdit edit'); dpm($edit);
+    // Get any additional mappings.
+    if (($mappings = $this->getSynchMappings($ldap_server->sid))) {
+      // Loop over the mappings.
+      foreach ($mappings as $field_key => $field_detail) {
+        // Make sure this mapping is relevant to the sync context.
+        if (in_array($synch_context, $field_detail['contexts']) &&
+          // And that we have a value for this attribute in the ldap entry.
+          ($value = $ldap_server->getAttributeValue($ldap_user, $field_detail['ldap_source']))) {
+          // Explode the value type (field/property) and name from the key.
+          list($value_type, $value_name) = explode('.', $field_key);
+          // Are we dealing with a field?
+          if ($value_type == 'field') {
+            // Field api field - first we get the field.
+            $field = field_info_field($value_name);
+            // Then the columns for the field in the schema.
+            $columns = array_keys($field['columns']);
+            // Then we convert the value into an array if it's scalar.
+            $values = $field['cardinality'] == 1 ? array($value) : (array) $value;
+
+            $items = array();
+            // Loop over the values and set them in our $items array.
+            foreach ($values as $delta => $value) {
+              if (isset($value)) {
+                // We set the first column value only, this is consistent with
+                // the Entity Api (@see entity_metadata_field_property_set).
+                $items[$delta][$columns[0]] = $value;
+              }
+            }
+            // Add them to our edited item.
+            $edit[$value_name][LANGUAGE_NONE] = $items;
+          }
+          elseif ($value_type == 'property') {
+            // Straight property.
+            $edit[$value_name] = $value;
+          }
+        }
+      }
+    }
+    // Allow other modules to have a say.
+    drupal_alter('ldap_user_edit_user', $edit, $ldap_user, $ldap_server, $synch_context);
   }
 
-
 } // end LdapUserConf class
diff --git a/ldap_user/ldap_user.api.php b/ldap_user/ldap_user.api.php
index 782c165..e26a3eb 100644
--- a/ldap_user/ldap_user.api.php
+++ b/ldap_user/ldap_user.api.php
@@ -40,3 +40,22 @@ function hook_ldap_user_targets_list_alter(&$available_user_targets, &$ldap_serv
   */
 
 }
+
+/**
+ * Allow modules to alter the user object in the context of an ldap entry
+ * during synchronization
+ *
+ * @param array $edit
+ *   The edit array (see hook_user_insert). Make changes to this object as
+ *   required.
+ * @param array $ldap_user
+ *   Array, the ldap user object relating to the drupal user
+ * @param object $ldap_server
+ *   The LdapServer object from which the ldap entry was fetched
+ * @param int $synch_context
+ *   The synch context, refer to the constants in ldap_user for more info
+ *
+*/
+function hook_ldap_user_edit_user_alter(&$edit, &$ldap_user, $ldap_server, $synch_context) {
+  $edit['myfield'] = $ldap_server->getAttributeValue($ldap_user, 'myfield');
+}
diff --git a/ldap_user/ldap_user.module b/ldap_user/ldap_user.module
index ea1716e..d401127 100644
--- a/ldap_user/ldap_user.module
+++ b/ldap_user/ldap_user.module
@@ -121,21 +121,22 @@ function ldap_user_conf($type = NULL, $reset = FALSE) {
 
 
 /**
- * implements hook_ldap_attributes_needed_alter()
+ * Implements hook_ldap_attributes_needed_alter().
  */
-function ldap_user_ldap_attributes_needed_alter(&$attributes, $sych_context, $ldap_server) {
-
-  //@todo need to load all ldap_user attributes used in synch mapping and add to list based on synch context.
- // dpm("ldap_user_ldap_attributes_needed_alter"); dpm($attributes); dpm($ldap_server); dpm($sych_context);
+function ldap_user_ldap_attributes_needed_alter(&$attributes, $synch_context, $ldap_server) {
   $attributes[] = 'dn';
   if ($ldap_server) { // puid attributes are server specific
     if (is_scalar($ldap_server)) {
       $ldap_server = ldap_servers_get_servers($ldap_server, 'enabled', TRUE);
     }
 
-    switch ($sych_context) {
+    switch ($synch_context) {
       case LDAP_USER_SYNCH_CONTEXT_INSERT_DRUPAL_USER:
       case LDAP_USER_SYNCH_CONTEXT_UPDATE_DRUPAL_USER:
+        // Load the user configuration.
+        $conf = ldap_user_conf();
+        // Add the attributes required by the user configuration.
+        $attributes += $conf->getRequiredAttributes($synch_context);
         $attributes[] = $ldap_server->user_attr;
         $attributes[] = $ldap_server->mail_attr;
         ldap_servers_extract_attributes_from_token($attributes,  $ldap_server->mail_template);
@@ -300,6 +301,21 @@ function ldap_user_user_login(&$edit, $account) {
 }
 
 /**
+ * Implements hook_user_presave().
+*/
+function ldap_user_user_presave(&$user_edit, $account, $category) {
+  $ldap_user_conf = ldap_user_conf();
+  $synch_context = $account->is_new ? LDAP_USER_SYNCH_CONTEXT_INSERT_DRUPAL_USER : LDAP_USER_SYNCH_CONTEXT_UPDATE_DRUPAL_USER;
+  // Update the Drupal user object from the LDAP account.
+  $ldap_user_conf->synchToDrupalAccount($account, $user_edit, $synch_context, NULL, FALSE);
+  // Make sure we've not removed the email address.
+  if (empty($user_edit['mail']) && !empty($account->mail)) {
+    // Use the original value.
+    $user_edit['mail'] = $account->mail;
+  }
+}
+
+/**
  * Implements hook_user_insert().
  *
  */
@@ -311,8 +327,6 @@ function ldap_user_user_insert(&$user_edit, $account, $category) {
   if ($account->status && in_array(LDAP_USER_LDAP_ENTRY_CREATION_ON_CREATE, $ldap_user_conf->ldapEntryProvisionEvents)) {
     $results = $ldap_user_conf->provisionLdapEntry($account, $synch_context);
   }
-
-  $ldap_user_conf->synchToDrupalAccount($account, $user_edit, $synch_context, NULL, FALSE);
   $ldap_user_conf->synchToLdapEntry($account, $user_edit, $synch_context, NULL, FALSE);
 }
 
@@ -329,8 +343,6 @@ function ldap_user_user_update(&$user_edit, $account, $category) {
   if ($status_enabled && in_array(LDAP_USER_LDAP_ENTRY_CREATION_ON_CREATE, $ldap_user_conf->ldapEntryProvisionEvents)) {
     $result = $ldap_user_conf->provisionLdapEntry($account, $synch_context);
   }
-
-  $ldap_user_conf->synchToDrupalAccount($account, $user_edit, $synch_context, NULL, FALSE);
   $ldap_user_conf->synchToLdapEntry($account, $user_edit, $synch_context, NULL, FALSE);
 }
 
