diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php
index ad75a38436983bb236084227771ea5ae264e0cec..adbcf6ff414ec2d1a662dbcf00230f4f8a8e1a10 100644
--- a/apps/user_ldap/ajax/wizard.php
+++ b/apps/user_ldap/ajax/wizard.php
@@ -39,13 +39,29 @@ if(!isset($_POST['ldap_serverconfig_chooser'])) {
 }
 $prefix = $_POST['ldap_serverconfig_chooser'];
 
-$ldapWrapper = new OCA\user_ldap\lib\LDAP();
+$ldapWrapper = new \OCA\user_ldap\lib\LDAP();
 $configuration = new \OCA\user_ldap\lib\Configuration($prefix);
-$wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper);
+
+$con = new \OCA\user_ldap\lib\Connection($ldapWrapper, '', null);
+$con->setConfiguration($configuration->getConfiguration());
+$con->ldapConfigurationActive = true;
+$con->setIgnoreValidation(true);
+
+$userManager = new \OCA\user_ldap\lib\user\Manager(
+	\OC::$server->getConfig(),
+	new \OCA\user_ldap\lib\FilesystemHelper(),
+	new \OCA\user_ldap\lib\LogWrapper(),
+	\OC::$server->getAvatarManager(),
+	new \OCP\Image());
+
+$access = new \OCA\user_ldap\lib\Access($con, $ldapWrapper, $userManager);
+
+$wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper, $access);
 
 switch($action) {
 	case 'guessPortAndTLS':
 	case 'guessBaseDN':
+	case 'detectEmailAttribute':
 	case 'determineGroupMemberAssoc':
 	case 'determineUserObjectClasses':
 	case 'determineGroupObjectClasses':
diff --git a/apps/user_ldap/js/ldapFilter.js b/apps/user_ldap/js/ldapFilter.js
index df3bd67aec2cc4d6e1d0a8b1b3387ec0603c2af5..e9f60e7ba3c9497352f8e7f7542d5e413bbb39ed 100644
--- a/apps/user_ldap/js/ldapFilter.js
+++ b/apps/user_ldap/js/ldapFilter.js
@@ -14,7 +14,7 @@ function LdapFilter(target)  {
 	}
 }
 
-LdapFilter.prototype.compose = function() {
+LdapFilter.prototype.compose = function(callback) {
 	var action;
 
 	if(this.locked) {
@@ -50,6 +50,9 @@ LdapFilter.prototype.compose = function() {
 				LdapWizard.countGroups();
 				LdapWizard.detectGroupMemberAssoc();
 			}
+			if(typeof callback !== 'undefined') {
+				callback();
+			}
 		},
 		function () {
 			console.log('LDAP Wizard: could not compose filter. '+
diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js
index 87d755697cb19974c3c0ff1dcfdc1b1e64031965..fd84ca1980b2a2f89bc1c22f33bfb7a208e9edeb 100644
--- a/apps/user_ldap/js/settings.js
+++ b/apps/user_ldap/js/settings.js
@@ -340,6 +340,14 @@ var LdapWizard = {
 		LdapWizard._countThings('countUsers');
 	},
 
+	detectEmailAttribute: function() {
+		param = 'action=detectEmailAttribute'+
+				'&ldap_serverconfig_chooser='+
+				encodeURIComponent($('#ldap_serverconfig_chooser').val());
+		//runs in the background, no callbacks necessary
+		LdapWizard.ajax(param, LdapWizard.applyChanges, function(){});
+	},
+
 	detectGroupMemberAssoc: function() {
 		param = 'action=determineGroupMemberAssoc'+
 				'&ldap_serverconfig_chooser='+
@@ -577,7 +585,7 @@ var LdapWizard = {
 	postInitUserFilter: function() {
 		if(LdapWizard.userFilterObjectClassesHasRun &&
 			LdapWizard.userFilterAvailableGroupsHasRun) {
-			LdapWizard.userFilter.compose();
+			LdapWizard.userFilter.compose(LdapWizard.detectEmailAttribute);
 			LdapWizard.countUsers();
 		}
 	},
@@ -619,6 +627,7 @@ var LdapWizard = {
 
 		if(triggerObj.id == 'ldap_userlist_filter') {
 			LdapWizard.countUsers();
+			LdapWizard.detectEmailAttribute();
 		} else if(triggerObj.id == 'ldap_group_filter') {
 			LdapWizard.countGroups();
 			LdapWizard.detectGroupMemberAssoc();
@@ -656,9 +665,12 @@ var LdapWizard = {
 		LdapWizard._save($('#'+originalObj)[0], $.trim(values));
 		if(originalObj == 'ldap_userfilter_objectclass'
 		   || originalObj == 'ldap_userfilter_groups') {
-			LdapWizard.userFilter.compose();
+			LdapWizard.userFilter.compose(LdapWizard.detectEmailAttribute);
 			//when user filter is changed afterwards, login filter needs to
 			//be adjusted, too
+			if(!LdapWizard.loginFilter) {
+				LdapWizard.initLoginFilter();
+			}
 			LdapWizard.loginFilter.compose();
 		} else if(originalObj == 'ldap_loginfilter_attributes') {
 			LdapWizard.loginFilter.compose();
@@ -720,7 +732,7 @@ var LdapWizard = {
 			LdapWizard._save({ id: modeKey }, LdapWizard.filterModeAssisted);
 			if(moc.indexOf('user') >= 0) {
 				LdapWizard.blacklistRemove('ldap_userlist_filter');
-				LdapWizard.userFilter.compose();
+				LdapWizard.userFilter.compose(LdapWizard.detectEmailAttribute);
 			} else {
 				LdapWizard.blacklistRemove('ldap_group_filter');
 				LdapWizard.groupFilter.compose();
diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php
index 0cec493d9ed07bf8cbf7bbe16d71d2e8b0020c21..4118b45bc3504e1840942a1b9569451881bc3867 100644
--- a/apps/user_ldap/lib/wizard.php
+++ b/apps/user_ldap/lib/wizard.php
@@ -25,6 +25,7 @@ namespace OCA\user_ldap\lib;
 
 class Wizard extends LDAPUtility {
 	static protected $l;
+	protected $access;
 	protected $cr;
 	protected $configuration;
 	protected $result;
@@ -48,12 +49,13 @@ class Wizard extends LDAPUtility {
 	 * @param Configuration $configuration an instance of Configuration
 	 * @param ILDAPWrapper $ldap an instance of ILDAPWrapper
 	 */
-	public function __construct(Configuration $configuration, ILDAPWrapper $ldap) {
+	public function __construct(Configuration $configuration, ILDAPWrapper $ldap, Access $access) {
 		parent::__construct($ldap);
 		$this->configuration = $configuration;
 		if(is_null(Wizard::$l)) {
 			Wizard::$l = \OC_L10N::get('user_ldap');
 		}
+		$this->access = $access;
 		$this->result = new WizardResult;
 	}
 
@@ -78,11 +80,10 @@ class Wizard extends LDAPUtility {
 			throw new \Exception('Requirements not met', 400);
 		}
 
-		$ldapAccess = $this->getAccess();
 		if($type === 'groups') {
-			$result =  $ldapAccess->countGroups($filter);
+			$result =  $this->access->countGroups($filter);
 		} else if($type === 'users') {
-			$result = $ldapAccess->countUsers($filter);
+			$result = $this->access->countUsers($filter);
 		} else {
 			throw new \Exception('internal error: invald object type', 500);
 		}
@@ -128,6 +129,77 @@ class Wizard extends LDAPUtility {
 		return $this->result;
 	}
 
+	/**
+	 * counts users with a specified attribute
+	 * @param string $attr
+	 * @return int|bool
+	 */
+	public function countUsersWithAttribute($attr) {
+		if(!$this->checkRequirements(array('ldapHost',
+										   'ldapPort',
+										   'ldapBase',
+										   'ldapUserFilter',
+										   ))) {
+			return  false;
+		}
+
+		$filter = $this->access->combineFilterWithAnd(array(
+			$this->configuration->ldapUserFilter,
+			$attr . '=*'
+		));
+
+		return $this->access->countUsers($filter);
+	}
+
+	/**
+	 * detects the most often used email attribute for users applying to the
+	 * user list filter. If a setting is already present that returns at least
+	 * one hit, the detection will be canceled.
+	 * @return WizardResult|bool
+	 */
+	public function detectEmailAttribute() {
+		if(!$this->checkRequirements(array('ldapHost',
+										   'ldapPort',
+										   'ldapBase',
+										   'ldapUserFilter',
+										   ))) {
+			return  false;
+		}
+
+		$attr = $this->configuration->ldapEmailAttribute;
+		if(!empty($attr)) {
+			$count = intval($this->countUsersWithAttribute($attr));
+			if($count > 0) {
+				return false;
+			}
+			$writeLog = true;
+		} else {
+			$writeLog = false;
+		}
+
+		$emailAttributes = array('mail', 'mailPrimaryAddress');
+		$winner = '';
+		$maxUsers = 0;
+		foreach($emailAttributes as $attr) {
+			$count = $this->countUsersWithAttribute($attr);
+			if($count > $maxUsers) {
+				$maxUsers = $count;
+				$winner = $attr;
+			}
+		}
+
+		if($winner !== '') {
+			$this->result->addChange('ldap_email_attr', $winner);
+			if($writeLog) {
+				\OCP\Util::writeLog('user_ldap', 'The mail attribute has ' .
+					'automatically been reset, because the original value ' .
+					'did not return any results.', \OCP\Util::INFO);
+			}
+		}
+
+		return $this->result;
+	}
+
 	/**
 	 * @return WizardResult
 	 * @throws \Exception
@@ -289,7 +361,6 @@ class Wizard extends LDAPUtility {
 	 */
 	public function fetchGroups($dbKey, $confKey) {
 		$obclasses = array('posixGroup', 'group', 'zimbraDistributionList', 'groupOfNames');
-		$ldapAccess = $this->getAccess();
 
 		$filterParts = array();
 		foreach($obclasses as $obclass) {
@@ -298,15 +369,15 @@ class Wizard extends LDAPUtility {
 		//we filter for everything
 		//- that looks like a group and
 		//- has the group display name set
-		$filter = $ldapAccess->combineFilterWithOr($filterParts);
-		$filter = $ldapAccess->combineFilterWithAnd(array($filter, 'cn=*'));
+		$filter = $this->access->combineFilterWithOr($filterParts);
+		$filter = $this->access->combineFilterWithAnd(array($filter, 'cn=*'));
 
 		$groupNames = array();
 		$groupEntries = array();
 		$limit = 400;
 		$offset = 0;
 		do {
-			$result = $ldapAccess->searchGroups($filter, array('cn','dn'), $limit, $offset);
+			$result = $this->access->searchGroups($filter, array('cn'), $limit, $offset);
 			foreach($result as $item) {
 				$groupNames[] = $item['cn'];
 				$groupEntries[] = $item;
@@ -1104,27 +1175,6 @@ class Wizard extends LDAPUtility {
 		}
 	}
 
-	/**
-	 * creates and returns an Access instance
-	 * @return \OCA\user_ldap\lib\Access
-	 */
-	private function getAccess() {
-		$con = new Connection($this->ldap, '', null);
-		$con->setConfiguration($this->configuration->getConfiguration());
-		$con->ldapConfigurationActive = true;
-		$con->setIgnoreValidation(true);
-
-		$userManager = new user\Manager(
-			\OC::$server->getConfig(),
-			new FilesystemHelper(),
-			new LogWrapper(),
-			\OC::$server->getAvatarManager(),
-			new \OCP\Image());
-
-		$ldapAccess = new Access($con, $this->ldap, $userManager);
-		return $ldapAccess;
-	}
-
 	/**
 	 * @return bool|mixed
 	 */
diff --git a/apps/user_ldap/tests/wizard.php b/apps/user_ldap/tests/wizard.php
index 50461432c421d9c8ca0dcd0433ac45f49df57cbf..1f420f9ee8a7c59f815b17e8a311f7307fd24260 100644
--- a/apps/user_ldap/tests/wizard.php
+++ b/apps/user_ldap/tests/wizard.php
@@ -43,16 +43,29 @@ class Test_Wizard extends \PHPUnit_Framework_TestCase {
 	}
 
 	private function getWizardAndMocks() {
-		static $conMethods;
-
-		if(is_null($conMethods)) {
-			$conMethods = get_class_methods('\OCA\user_ldap\lib\Configuration');
+		static $confMethods;
+		static $connMethods;
+		static $accMethods;
+
+		if(is_null($confMethods)) {
+			$confMethods = get_class_methods('\OCA\user_ldap\lib\Configuration');
+			$connMethods = get_class_methods('\OCA\user_ldap\lib\Connection');
+			$accMethods  = get_class_methods('\OCA\user_ldap\lib\Access');
 		}
 		$lw   = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper');
 		$conf = $this->getMock('\OCA\user_ldap\lib\Configuration',
-							   $conMethods,
+							   $confMethods,
 							   array($lw, null, null));
-		return array(new Wizard($conf, $lw), $conf, $lw);
+
+		$connector = $this->getMock('\OCA\user_ldap\lib\Connection',
+			$connMethods, array($lw, null, null));
+		$um = $this->getMockBuilder('\OCA\user_ldap\lib\user\Manager')
+					->disableOriginalConstructor()
+					->getMock();
+		$access = $this->getMock('\OCA\user_ldap\lib\Access',
+			$accMethods, array($connector, $lw, $um));
+
+		return array(new Wizard($conf, $lw, $access), $conf, $lw, $access);
 	}
 
 	private function prepareLdapWrapperForConnections(&$ldap) {
@@ -207,6 +220,144 @@ class Test_Wizard extends \PHPUnit_Framework_TestCase {
 		unset($uidnumber);
 	}
 
+	public function testDetectEmailAttributeAlreadySet() {
+		list($wizard, $configuration, $ldap, $access)
+			= $this->getWizardAndMocks();
+
+		$configuration->expects($this->any())
+			->method('__get')
+			->will($this->returnCallback(function ($name) {
+				if($name === 'ldapEmailAttribute') {
+					return 'myEmailAttribute';
+				} else {
+					//for requirement checks
+					return 'let me pass';
+				}
+			}));
+
+		$access->expects($this->once())
+			->method('countUsers')
+			->will($this->returnValue(42));
+
+		$wizard->detectEmailAttribute();
+	}
+
+	public function testDetectEmailAttributeOverrideSet() {
+		list($wizard, $configuration, $ldap, $access)
+			= $this->getWizardAndMocks();
+
+		$configuration->expects($this->any())
+			->method('__get')
+			->will($this->returnCallback(function ($name) {
+				if($name === 'ldapEmailAttribute') {
+					return 'myEmailAttribute';
+				} else {
+					//for requirement checks
+					return 'let me pass';
+				}
+			}));
+
+		$access->expects($this->exactly(3))
+			->method('combineFilterWithAnd')
+			->will($this->returnCallback(function ($filterParts) {
+				return str_replace('=*', '', array_pop($filterParts));
+			}));
+
+		$access->expects($this->exactly(3))
+			->method('countUsers')
+			->will($this->returnCallback(function ($filter) {
+				if($filter === 'myEmailAttribute') {
+					return 0;
+				} else if($filter === 'mail') {
+					return 3;
+				} else if($filter === 'mailPrimaryAddress') {
+					return 17;
+				}
+				var_dump($filter);
+			}));
+
+		$result = $wizard->detectEmailAttribute()->getResultArray();
+		$this->assertSame('mailPrimaryAddress',
+			$result['changes']['ldap_email_attr']);
+	}
+
+	public function testDetectEmailAttributeFind() {
+		list($wizard, $configuration, $ldap, $access)
+			= $this->getWizardAndMocks();
+
+		$configuration->expects($this->any())
+			->method('__get')
+			->will($this->returnCallback(function ($name) {
+				if($name === 'ldapEmailAttribute') {
+					return '';
+				} else {
+					//for requirement checks
+					return 'let me pass';
+				}
+			}));
+
+		$access->expects($this->exactly(2))
+			->method('combineFilterWithAnd')
+			->will($this->returnCallback(function ($filterParts) {
+				return str_replace('=*', '', array_pop($filterParts));
+			}));
+
+		$access->expects($this->exactly(2))
+			->method('countUsers')
+			->will($this->returnCallback(function ($filter) {
+				if($filter === 'myEmailAttribute') {
+					return 0;
+				} else if($filter === 'mail') {
+					return 3;
+				} else if($filter === 'mailPrimaryAddress') {
+					return 17;
+				}
+				var_dump($filter);
+			}));
+
+		$result = $wizard->detectEmailAttribute()->getResultArray();
+		$this->assertSame('mailPrimaryAddress',
+			$result['changes']['ldap_email_attr']);
+	}
+
+	public function testDetectEmailAttributeFindNothing() {
+		list($wizard, $configuration, $ldap, $access)
+			= $this->getWizardAndMocks();
+
+		$configuration->expects($this->any())
+			->method('__get')
+			->will($this->returnCallback(function ($name) {
+				if($name === 'ldapEmailAttribute') {
+					return 'myEmailAttribute';
+				} else {
+					//for requirement checks
+					return 'let me pass';
+				}
+			}));
+
+		$access->expects($this->exactly(3))
+			->method('combineFilterWithAnd')
+			->will($this->returnCallback(function ($filterParts) {
+				return str_replace('=*', '', array_pop($filterParts));
+			}));
+
+		$access->expects($this->exactly(3))
+			->method('countUsers')
+			->will($this->returnCallback(function ($filter) {
+				if($filter === 'myEmailAttribute') {
+					return 0;
+				} else if($filter === 'mail') {
+					return 0;
+				} else if($filter === 'mailPrimaryAddress') {
+					return 0;
+				}
+				var_dump($filter);
+			}));
+
+		$result = $wizard->detectEmailAttribute();
+		$this->assertSame(false, $result->hasChanges());
+	}
+
 	public function testCumulativeSearchOnAttributeSkipReadDN() {
 		// tests that there is no infinite loop, when skipping already processed
 		// DNs (they can be returned multiple times for multiple filters )