diff --git a/src/main/java/org/olat/core/id/Identity.java b/src/main/java/org/olat/core/id/Identity.java
index 3fa1da336ed8c2d9af9bc72cf8e8fc2631be77c3..e4b269251dfab6fde6e2da00814554ad76359cb1 100644
--- a/src/main/java/org/olat/core/id/Identity.java
+++ b/src/main/java/org/olat/core/id/Identity.java
@@ -38,18 +38,20 @@ import org.olat.basesecurity.IdentityRef;
  */
 public interface Identity extends CreateInfo, IdentityRef, Persistable {
 
-	// status = 1..99    User with this status are visibale (e.g. user search)
-	//          100..199 User with this status are invisibale (e.g. user search)
+	// status = 1..99    User with this status are visible (e.g. user search)
+	//          100..199 User with this status are invisible (e.g. user search)
 	/** Identity has a permanent olat user account and will be never listen in user-deletion process. */
-	public static Integer STATUS_PERMANENT = 1;
+	public static final Integer STATUS_PERMANENT = 1;
 	/** Identity has access to olat-system. */ 
-	public static Integer STATUS_ACTIV     = 2;
+	public static final Integer STATUS_ACTIV = 2;
 	/** Limit for visible identities, all identities with status < LIMIT will be listed in search etc. */
-	public static Integer STATUS_VISIBLE_LIMIT = 100;
+	public static final Integer STATUS_VISIBLE_LIMIT = 100;
 	/** Identity can not login and will not be listed (only on login-denied list). */
-	public static Integer STATUS_LOGIN_DENIED = 101;
+	public static final Integer STATUS_LOGIN_DENIED = 101;
+	/** Identity can not login and will not be listed (only on pending list). */
+	public static final Integer STATUS_PENDING = 102;
 	/** Identity is deleted and has no access to olat-system and is not visible (except administrators). */
-	public static Integer STATUS_DELETED   = 199;
+	public static final Integer STATUS_DELETED   = 199;
 	
     /**
      * @return The username, (login name, nickname..)
diff --git a/src/main/java/org/olat/registration/RegistrationAdminController.java b/src/main/java/org/olat/registration/RegistrationAdminController.java
index 54fabbedc6640836a2bd0c2b29dd076144be2d4c..5a44d3d5aaaa633df23845bf5fa1da12cf8daa22 100644
--- a/src/main/java/org/olat/registration/RegistrationAdminController.java
+++ b/src/main/java/org/olat/registration/RegistrationAdminController.java
@@ -41,6 +41,7 @@ import org.olat.core.gui.translator.Translator;
 import org.olat.core.helpers.Settings;
 import org.olat.core.id.Organisation;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.mail.MailHelper;
 import org.olat.user.UserPropertiesConfig;
 import org.olat.user.propertyhandlers.Generic127CharTextPropertyHandler;
 import org.olat.user.propertyhandlers.UserPropertyHandler;
@@ -59,17 +60,34 @@ public class RegistrationAdminController extends FormBasicController {
 	private MultipleSelectionElement registrationLoginElement;
 	private MultipleSelectionElement staticPropElement;
 	private SingleSelection propertyElement;
+	private SingleSelection pendingRegistrationStatusEl;
+	private TextElement pendingRegistrationNotificationEl;
+	private PropertyNameValueElements pendingProperty1Els;
+	private PropertyNameValueElements pendingProperty2Els;
+	private PropertyNameValueElements pendingProperty3Els;
+	private PropertyNameValueElements pendingProperty4Els;
+	private PropertyNameValueElements pendingProperty5Els;
 	private TextElement propertyValueElement;
 	private TextElement exampleElement;
 	private TextElement domainListElement;
 	private TextElement validUntilGuiEl;
 	private TextElement validUntilRestEl;
 	private FormLayoutContainer domainsContainer;
+	private FormLayoutContainer pendingPropContainer;
 	private FormLayoutContainer staticPropContainer;
 	
+
+	private static final String[] pendingRegistrationKeys = new String[] { 
+			RegistrationPendingStatus.active.name(),
+			RegistrationPendingStatus.pending.name(),
+			RegistrationPendingStatus.pendingMatchingProperties.name()
+		};
+	
 	private static final String[] enableRegistrationKeys = new String[]{ "on" };
-	private String[] propertyKeys;
-	private String[] propertyValues;
+	private final String[] propertyKeys;
+	private final String[] propertyValues;
+	private final String[] pendingPropertyKeys;
+	private final String[] pendingPropertyValues;
 	
 	@Autowired
 	private RegistrationModule registrationModule;
@@ -87,7 +105,6 @@ public class RegistrationAdminController extends FormBasicController {
 		//decorate the translator
 		userPropTranslator = userPropertiesConfig.getTranslator(getTranslator());
 
-		
 		List<UserPropertyHandler> allPropertyHandlers = userPropertiesConfig.getAllUserPropertyHandlers();
 		List<UserPropertyHandler> propertyHandlers = new ArrayList<>(allPropertyHandlers.size());
 		for(UserPropertyHandler handler:allPropertyHandlers) {
@@ -106,6 +123,16 @@ public class RegistrationAdminController extends FormBasicController {
 			propertyValues[1 + count++] = userPropTranslator.translate(propertyHandler.i18nFormElementLabelKey());
 		}
 		
+		pendingPropertyKeys = new String[allPropertyHandlers.size() + 1];
+		pendingPropertyValues = new String[allPropertyHandlers.size() + 1];
+		count = 0;
+		pendingPropertyKeys[0] = "-";
+		pendingPropertyValues[0] = "";
+		for(UserPropertyHandler propertyHandler:allPropertyHandlers) {
+			pendingPropertyKeys[1 + count] = propertyHandler.getName();
+			pendingPropertyValues[1 + count++] = userPropTranslator.translate(propertyHandler.i18nFormElementLabelKey());
+		}
+		
 		initForm(ureq);
 	}
 
@@ -141,7 +168,24 @@ public class RegistrationAdminController extends FormBasicController {
 		String example = generateExampleCode();
 		exampleElement = uifactory.addTextAreaElement("registration.link.example", "admin.registrationLinkExample", 64000, 4, 65, true, false, example, settingsContainer);
 		
+		// pedning status
+		initPendingPropForm(formLayout);
 		//domain configuration
+		initDomainForm(formLayout);
+		//static property
+		initStaticPropForm(formLayout, enableRegistrationValues);
+		//static property
+		initRemoteLogin(formLayout);
+		
+		FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
+		buttonGroupLayout.setRootForm(mainForm);
+		uifactory.addFormSubmitButton("save", buttonGroupLayout);
+		formLayout.add(buttonGroupLayout);
+		
+		updateUI();	
+	}
+	
+	private void initDomainForm(FormItemContainer formLayout) {
 		domainsContainer = FormLayoutContainer.createDefaultFormLayout("domains", getTranslator());
 		domainsContainer.setRootForm(mainForm);
 		domainsContainer.setFormTitle(translate("admin.registration.domains.title"));
@@ -150,8 +194,55 @@ public class RegistrationAdminController extends FormBasicController {
 		uifactory.addStaticTextElement("admin.registration.domains.error", null, translate("admin.registration.domains.desc"), domainsContainer);
 		String domainsList = registrationModule.getDomainListRaw();
 		domainListElement = uifactory.addTextAreaElement("registration.domain.list", "admin.registration.domains", 64000, 10, 65, true, false, domainsList, domainsContainer);
+	}
+	
+	private void initPendingPropForm(FormItemContainer formLayout) {
+		pendingPropContainer = FormLayoutContainer.createDefaultFormLayout("propertiespending", getTranslator());
+		pendingPropContainer.setRootForm(mainForm);
+		pendingPropContainer.setFormTitle(translate("admin.registration.pending.status"));
+		formLayout.add(pendingPropContainer);
+		
+		String[] pendingRegistrationValues = new String[] {
+				translate("registration.pending.status.active"),
+				translate("registration.pending.status.pending"),
+				translate("registration.pending.status.pending.props")
+			};
+		pendingRegistrationStatusEl = uifactory.addDropdownSingleselect("registration.pending.status", pendingPropContainer, pendingRegistrationKeys, pendingRegistrationValues);
+		pendingRegistrationStatusEl.select(registrationModule.getRegistrationPendingStatus().name(), true);
+		pendingRegistrationStatusEl.addActionListener(FormEvent.ONCHANGE);
+	
+		pendingProperty1Els = initPendingProperty(1, registrationModule.getRegistrationPendingPropertyName1(), registrationModule.getRegistrationPendingPropertyValue1(), pendingPropContainer);
+		pendingProperty2Els = initPendingProperty(2, registrationModule.getRegistrationPendingPropertyName2(), registrationModule.getRegistrationPendingPropertyValue2(), pendingPropContainer);
+		pendingProperty3Els = initPendingProperty(3, registrationModule.getRegistrationPendingPropertyName3(), registrationModule.getRegistrationPendingPropertyValue3(), pendingPropContainer);
+		pendingProperty4Els = initPendingProperty(4, registrationModule.getRegistrationPendingPropertyName4(), registrationModule.getRegistrationPendingPropertyValue4(), pendingPropContainer);
+		pendingProperty5Els = initPendingProperty(5, registrationModule.getRegistrationPendingPropertyName5(), registrationModule.getRegistrationPendingPropertyValue5(), pendingPropContainer);
 
-		//static property
+		String email = "";
+		if(registrationModule.isRegistrationNotificationEmailEnabled()) {
+			email = registrationModule.getRegistrationNotificationEmail();
+		}
+		pendingRegistrationNotificationEl = uifactory.addTextElement("registration.pending.notification.mail", 2048, email, pendingPropContainer);
+	}
+	
+	private PropertyNameValueElements initPendingProperty(int pos, String propName, String propValue, FormLayoutContainer formLayout) {
+		SingleSelection pendingPropertyNameEl = uifactory.addDropdownSingleselect("registration.pending.prop.name" + pos, formLayout, pendingPropertyKeys, pendingPropertyValues);
+		boolean found = false;
+		for(int i=pendingPropertyKeys.length; i-->0; ) {
+			if(pendingPropertyKeys[i].equals(propName)) {
+				pendingPropertyNameEl.select(pendingPropertyKeys[i], true);
+				found = true;
+				break;
+			}
+		}
+		if(!found) {
+			pendingPropertyNameEl.select(pendingPropertyKeys[0], true);
+		}
+
+		TextElement pendingPropertyValueEl = uifactory.addTextElement("registration.pending.prop.value" + pos, 2048, propValue, formLayout);
+		return new PropertyNameValueElements(pendingPropertyNameEl, pendingPropertyValueEl);
+	}
+	
+	private void initStaticPropForm(FormItemContainer formLayout, String[] enableRegistrationValues) {
 		staticPropContainer = FormLayoutContainer.createDefaultFormLayout("propertiesmapping", getTranslator());
 		staticPropContainer.setRootForm(mainForm);
 		staticPropContainer.setFormTitle(translate("admin.registration.staticprop.title"));
@@ -173,8 +264,9 @@ public class RegistrationAdminController extends FormBasicController {
 		
 		String propertyValue = registrationModule.getStaticPropertyMappingValue();
 		propertyValueElement = uifactory.addTextElement("admin.registration.prop.value", "admin.registration.propertyValue", 255, propertyValue, staticPropContainer);
-		
-		//static property
+	}
+	
+	private void initRemoteLogin(FormItemContainer formLayout) {
 		FormLayoutContainer remoteLoginContainerContainer = FormLayoutContainer.createDefaultFormLayout("remotelogin", getTranslator());
 		remoteLoginContainerContainer.setRootForm(mainForm);
 		remoteLoginContainerContainer.setFormTitle(translate("remote.login.title"));
@@ -182,13 +274,6 @@ public class RegistrationAdminController extends FormBasicController {
 		
 		String remoteExample = generateRemoteLoginExampleCode();
 		uifactory.addTextAreaElement("remotelogin.example", "admin.registrationLinkExample", 64000, 4, 65, true, false, remoteExample, remoteLoginContainerContainer);
-		
-		FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
-		buttonGroupLayout.setRootForm(mainForm);
-		uifactory.addFormSubmitButton("save", buttonGroupLayout);
-		formLayout.add(buttonGroupLayout);
-		
-		updateUI();	
 	}
 	
 	private void initOrganisationsEl(FormLayoutContainer formLayout) {
@@ -232,6 +317,8 @@ public class RegistrationAdminController extends FormBasicController {
 		} else if (source == staticPropElement) {
 			registrationModule.setStaticPropertyMappingEnabled(staticPropElement.isSelected(0));
 			updateUI();
+		} else if(source == pendingRegistrationStatusEl) {
+			updateUI();
 		}
 		
 		super.formInnerEvent(ureq, source, event);
@@ -249,6 +336,17 @@ public class RegistrationAdminController extends FormBasicController {
 		boolean enableDomains = enableMain && (registrationLinkElement.isSelected(0) || registrationLoginElement.isSelected(0));
 		domainsContainer.setVisible(enableDomains);
 		
+		pendingPropContainer.setVisible(enableMain);
+		if(enableMain) {
+			boolean useProps = RegistrationPendingStatus.pendingMatchingProperties.name()
+					.equals(pendingRegistrationStatusEl.getSelectedKey());
+			pendingProperty1Els.setVisible(useProps);
+			pendingProperty2Els.setVisible(useProps);
+			pendingProperty3Els.setVisible(useProps);
+			pendingProperty4Els.setVisible(useProps);
+			pendingProperty5Els.setVisible(useProps);
+		}
+		
 		//static prop
 		boolean enableProps = enableMain && (registrationLinkElement.isSelected(0) || registrationLoginElement.isSelected(0));
 		staticPropContainer.setVisible(enableProps);
@@ -264,6 +362,14 @@ public class RegistrationAdminController extends FormBasicController {
 		allOk &= validateInteger(validUntilGuiEl, 1);
 		allOk &= validateInteger(validUntilRestEl, 1);
 		
+		allOk &= validatePropertyNameValuePair(pendingProperty1Els);
+		allOk &= validatePropertyNameValuePair(pendingProperty2Els);
+		allOk &= validatePropertyNameValuePair(pendingProperty3Els);
+		allOk &= validatePropertyNameValuePair(pendingProperty4Els);
+		allOk &= validatePropertyNameValuePair(pendingProperty5Els);
+		
+		allOk &= validateEmail(pendingRegistrationNotificationEl);
+		
 		String whiteList = domainListElement.getValue();
 		domainListElement.clearError();
 		if(StringHelper.containsNonWhitespace(whiteList)) {
@@ -305,6 +411,44 @@ public class RegistrationAdminController extends FormBasicController {
 		return allOk;
 	}
 	
+	private boolean validateEmail(TextElement el) {
+		boolean allOk = true;
+		
+		el.clearError();
+		if(StringHelper.containsNonWhitespace(el.getValue())) {
+			String[] emails = el.getValue().split("[,]");
+			for(String email:emails) {
+				if(!MailHelper.isValidEmailAddress(email)) {
+					el.setErrorKey("email.address.notregular", null);
+					allOk &= false;
+					break;
+				}
+			}
+		}
+
+		return allOk;
+	}
+	
+	private boolean validatePropertyNameValuePair(PropertyNameValueElements nameValueEls) {
+		boolean allOk = true;
+		
+		SingleSelection nameEl = nameValueEls.getPropertyNameEl();
+		TextElement valueEl = nameValueEls.getPropertyValueEl();
+		
+		nameEl.clearError();
+		valueEl.clearError();
+		if(!nameEl.isOneSelected()) {
+			nameEl.setErrorKey("form.legende.mandatory", null);
+			allOk &= false;
+		} else if(!nameEl.getSelectedKey().equals(propertyKeys[0])
+				&& !StringHelper.containsNonWhitespace(valueEl.getValue())) {
+			valueEl.setErrorKey("form.legende.mandatory", null);
+			allOk &= false;
+		}
+
+		return allOk;
+	}
+	
 	private boolean validateInteger(TextElement el, int min) {
 		boolean allOk = true;
 		el.clearError();
@@ -336,6 +480,23 @@ public class RegistrationAdminController extends FormBasicController {
 		if(organisationsEl.isOneSelected()) {
 			registrationModule.setselfRegistrationOrganisationKey(organisationsEl.getSelectedKey());
 		}
+		if(pendingRegistrationStatusEl.isOneSelected()) {
+			registrationModule.setRegistrationPendingStatus(RegistrationPendingStatus.valueOf(pendingRegistrationStatusEl.getSelectedKey()));
+		}
+		
+		registrationModule.setRegistrationPendingProperty1(pendingProperty1Els.getName(), pendingProperty1Els.getValue());
+		registrationModule.setRegistrationPendingProperty2(pendingProperty2Els.getName(), pendingProperty2Els.getValue());
+		registrationModule.setRegistrationPendingProperty3(pendingProperty3Els.getName(), pendingProperty3Els.getValue());
+		registrationModule.setRegistrationPendingProperty4(pendingProperty4Els.getName(), pendingProperty4Els.getValue());
+		registrationModule.setRegistrationPendingProperty5(pendingProperty5Els.getName(), pendingProperty5Els.getValue());
+		
+		String notificationEmail = pendingRegistrationNotificationEl.getValue();
+		if(StringHelper.containsNonWhitespace(notificationEmail)) {
+			registrationModule.setRegistrationNotificationEmailEnabled(true);
+			registrationModule.setRegistrationNotificationEmail(notificationEmail);
+		} else {
+			registrationModule.setRegistrationNotificationEmailEnabled(false);
+		}
 		
 		Integer validUntilHoursGui = Integer.parseInt(validUntilGuiEl.getValue());
 		registrationModule.setValidUntilHoursGui(validUntilHoursGui);
@@ -375,4 +536,40 @@ public class RegistrationAdminController extends FormBasicController {
 		    .append("</form>");
 		return code.toString();
 	}
+	
+	public class PropertyNameValueElements {
+		
+		private final SingleSelection propertyNameEl;
+		private final TextElement propertyValueEl;
+		
+		public PropertyNameValueElements(SingleSelection propertyNameEl, TextElement propertyValueEl) {
+			this.propertyNameEl = propertyNameEl;
+			this.propertyValueEl = propertyValueEl;
+		}
+
+		public SingleSelection getPropertyNameEl() {
+			return propertyNameEl;
+		}
+
+		public TextElement getPropertyValueEl() {
+			return propertyValueEl;
+		}
+		
+		public void setVisible(boolean visible) {
+			propertyNameEl.setVisible(visible);
+			propertyValueEl.setVisible(visible);
+		}
+		
+		public String getName() {
+			String key = propertyNameEl.getSelectedKey();
+			if(propertyKeys[0].equals(key)) {
+				key = "";
+			}
+			return key;
+		}
+		
+		public String getValue() {
+			return propertyValueEl.getValue();
+		}
+	}
 }
diff --git a/src/main/java/org/olat/registration/RegistrationController.java b/src/main/java/org/olat/registration/RegistrationController.java
index 15ea45a05ced4714aba7fedec4fc689409e1a5d7..b309c8515e157c721fc0db52406db0cf91be61a0 100644
--- a/src/main/java/org/olat/registration/RegistrationController.java
+++ b/src/main/java/org/olat/registration/RegistrationController.java
@@ -37,7 +37,6 @@ import java.util.Map;
 import org.olat.basesecurity.AuthHelper;
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.basesecurity.BaseSecurityModule;
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.chiefcontrollers.LanguageChangedEvent;
 import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
 import org.olat.core.dispatcher.DispatcherModule;
@@ -122,6 +121,8 @@ public class RegistrationController extends BasicController implements Activatea
 	private RegistrationModule registrationModule;
 	@Autowired
 	private RegistrationManager registrationManager;
+	@Autowired
+	private UserPropertiesConfig userPropertiesConfig;
 
 	/**
 	 * Controller implementing registration workflow.
@@ -495,7 +496,14 @@ public class RegistrationController extends BasicController implements Activatea
 		finishVC.contextPut("user", persitedIdentity.getUser());
 		finishVC.contextPut("locale", getLocale());
 		finishVC.contextPut("username", registrationForm.getLogin());
-		finishVC.contextPut("text", getTranslator().translate("step5.reg.text", new String[]{ registrationForm.getLogin() }));
+		
+		boolean pending = persitedIdentity.getStatus().equals(Identity.STATUS_PENDING);
+		if(pending) {
+			finishVC.contextPut("text", translate("step5.reg.pending", new String[]{ registrationForm.getLogin() }));
+		} else {
+			finishVC.contextPut("text", translate("step5.reg.text", new String[]{ registrationForm.getLogin() }));
+		}
+		finishVC.contextPut("pending", Boolean.valueOf(pending));
 		loginButton = LinkFactory.createButton("form.login", finishVC, this);
 		loginButton.setCustomEnabledLinkCSS("btn btn-primary");
 		loginButton.setUserObject(persitedIdentity);
@@ -530,7 +538,6 @@ public class RegistrationController extends BasicController implements Activatea
 			User persistedUser = persistedIdentity.getUser();
 			
 			//add eventually static value
-			UserPropertiesConfig userPropertiesConfig = CoreSpringFactory.getImpl(UserPropertiesConfig.class);
 			if(registrationModule.isStaticPropertyMappingEnabled()) {
 				String propertyName = registrationModule.getStaticPropertyMappingName();
 				String propertyValue = registrationModule.getStaticPropertyMappingValue();
@@ -564,7 +571,7 @@ public class RegistrationController extends BasicController implements Activatea
 			// persist changes in db
 			userManager.updateUserFromIdentity(persistedIdentity);
 			// send notification mail to sys admin
-			String notiEmail = CoreSpringFactory.getImpl(RegistrationModule.class).getRegistrationNotificationEmail();
+			String notiEmail = registrationModule.getRegistrationNotificationEmail();
 			if (notiEmail != null) {
 				registrationManager.sendNewUserNotificationMessage(notiEmail, persistedIdentity);
 			}
diff --git a/src/main/java/org/olat/registration/RegistrationManager.java b/src/main/java/org/olat/registration/RegistrationManager.java
index 25c29416c1e50a48b35e2c389245f1cf912de4ec..9b482c098342fe0d940878a7010a7becb8896bcf 100644
--- a/src/main/java/org/olat/registration/RegistrationManager.java
+++ b/src/main/java/org/olat/registration/RegistrationManager.java
@@ -47,7 +47,6 @@ import org.olat.basesecurity.BaseSecurity;
 import org.olat.basesecurity.OrganisationRoles;
 import org.olat.basesecurity.OrganisationService;
 import org.olat.basesecurity.model.OrganisationRefImpl;
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.helpers.Settings;
@@ -88,6 +87,11 @@ import com.thoughtworks.xstream.XStream;
 public class RegistrationManager implements UserDataDeletable, UserDataExportable {
 	
 	private static final OLog log = Tracing.createLoggerFor(RegistrationManager.class);
+	
+	private static final XStream xmlXStream = XStreamHelper.createXStreamInstance();
+	static {
+		XStream.setupDefaultSecurity(xmlXStream);
+	}
 
 	private static final int VALID_UNTIL_30_DAYS = 30*24;
 
@@ -98,6 +102,8 @@ public class RegistrationManager implements UserDataDeletable, UserDataExportabl
 	@Autowired
 	private DB dbInstance;
 	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
 	private MailManager mailManager;
 	@Autowired
 	private BaseSecurity securityManager;
@@ -204,14 +210,53 @@ public class RegistrationManager implements UserDataDeletable, UserDataExportabl
 		}
 		if (identity == null) {
 			return null;
+		} else if(pending(identity)) {
+			identity = securityManager.saveIdentityStatus(identity, Identity.STATUS_PENDING, identity);
 		}
 		deleteTemporaryKey(tk);
 		return identity;
 	}
+	
+	private boolean pending(Identity identity) {
+		boolean pending = false;
+		RegistrationPendingStatus status = registrationModule.getRegistrationPendingStatus();
+		if(status == RegistrationPendingStatus.pending) {
+			pending = true;
+		} else if(status == RegistrationPendingStatus.pendingMatchingProperties) {
+			User user = identity.getUser();
+			@SuppressWarnings("static-access")
+			Locale locale = i18nModule.getDefaultLocale();
+			pending |= matchProperty(user, registrationModule.getRegistrationPendingPropertyName1(), registrationModule.getRegistrationPendingPropertyValue1(), locale);
+			pending |= matchProperty(user, registrationModule.getRegistrationPendingPropertyName2(), registrationModule.getRegistrationPendingPropertyValue2(), locale);
+			pending |= matchProperty(user, registrationModule.getRegistrationPendingPropertyName3(), registrationModule.getRegistrationPendingPropertyValue3(), locale);
+			pending |= matchProperty(user, registrationModule.getRegistrationPendingPropertyName4(), registrationModule.getRegistrationPendingPropertyValue4(), locale);
+			pending |= matchProperty(user, registrationModule.getRegistrationPendingPropertyName5(), registrationModule.getRegistrationPendingPropertyValue5(), locale);
+		}
+		return pending;
+	}
+	
+	private boolean matchProperty(User user, String propName, String propValue, Locale locale) {
+		boolean match = false;
+		
+		if(StringHelper.containsNonWhitespace(propName) && StringHelper.containsNonWhitespace(propValue)) {
+			String val = user.getProperty(propName, locale);
+			
+			if(propValue.equalsIgnoreCase(val)) {
+				match = true;
+			} else if(UserConstants.EMAIL.equals(propName) || UserConstants.INSTITUTIONALEMAIL.equals(propName)) {
+				String valLow = val.toLowerCase();
+				String propValueLow = propValue.toLowerCase();
+				match = valLow.contains(propValueLow);
+			}
+		}
+		
+		return match;
+	}
 
 	/**
-	 * Send a notification messaged to the given notification email address about the registratoin of 
+	 * Send a notification messaged to the given notification email address about the registration of 
 	 * the given new identity.
+	 * 
 	 * @param notificationMailAddress Email address who should be notified. MUST NOT BE NULL
 	 * @param newIdentity The newly registered Identity
 	 */
@@ -219,9 +264,15 @@ public class RegistrationManager implements UserDataDeletable, UserDataExportabl
 		Address from;
 		Address[] to;
 		try {
-			// fxdiff: change from/replyto, see FXOLAT-74
 			from = new InternetAddress(WebappHelper.getMailConfig("mailReplyTo"));
-			to = new Address[] { new InternetAddress(notificationMailAddress)};
+			String[] notificationMailAddressArr = notificationMailAddress.split("[,]");
+			List<Address> toList = new ArrayList<>();
+			for(int i=notificationMailAddressArr.length; i-->0; ) {
+				if(StringHelper.containsNonWhitespace(notificationMailAddressArr[i])) {
+					toList.add(new InternetAddress(notificationMailAddressArr[i]));
+				}
+			}
+			to = toList.toArray(new Address[toList.size()]);
 		} catch (AddressException e) {
 			log.error("Could not send registration notification message, bad mail address", e);
 			return;
@@ -427,12 +478,9 @@ public class RegistrationManager implements UserDataDeletable, UserDataExportabl
 	public boolean isEmailReserved(String emailAddress) {
 		if (!StringHelper.containsNonWhitespace(emailAddress)) return false;
 		
-		RegistrationManager rm = CoreSpringFactory.getImpl(RegistrationManager.class);
-		List<TemporaryKey> tk = rm.loadTemporaryKeyByAction(RegistrationManager.EMAIL_CHANGE);
+		List<TemporaryKey> tk = loadTemporaryKeyByAction(RegistrationManager.EMAIL_CHANGE);
 		for (TemporaryKey temporaryKey : tk) {
-			XStream xml = XStreamHelper.createXStreamInstance();
-			@SuppressWarnings("unchecked")
-			Map<String, String> mails = (Map<String, String>) xml.fromXML(temporaryKey.getEmailAddress());
+			Map<String, String> mails = readTemporaryValue(temporaryKey.getEmailAddress());
 			if (emailAddress.equalsIgnoreCase(mails.get("changedEMail"))) {
 				return true;
 			}
@@ -498,6 +546,11 @@ public class RegistrationManager implements UserDataDeletable, UserDataExportabl
 	public void revokeConfirmedDisclaimer(Identity identity) {
 		propertyManager.deleteProperties(identity, null, null, "user", "dislaimer_accepted");		
 	}
+	
+	@SuppressWarnings("unchecked")
+	public Map<String, String> readTemporaryValue(String value) {
+		return (Map<String, String>)xmlXStream.fromXML(value);
+	}
 
 	private String createRegistrationKey(String email, String ip) {
 		String random = UUID.randomUUID().toString();
diff --git a/src/main/java/org/olat/registration/RegistrationModule.java b/src/main/java/org/olat/registration/RegistrationModule.java
index 1d4300a9b5d5a3bf667c3123a6e9b5edc82aedab..81f09125146753adb20fcc1b31c02399735ff78b 100644
--- a/src/main/java/org/olat/registration/RegistrationModule.java
+++ b/src/main/java/org/olat/registration/RegistrationModule.java
@@ -74,6 +74,28 @@ public class RegistrationModule extends AbstractSpringModule {
 	private boolean registrationNotificationEmailEnabled;
 	@Value("${registration.notificationEmail}")
 	private String registrationNotificationEmail;
+	@Value("${registration.pending.status:active}")
+	private String registrationPendingStatus;
+	@Value("${registration.pending.property.name1:}")
+	private String registrationPendingPropertyName1;
+	@Value("${registration.pending.property.value1:}")
+	private String registrationPendingPropertyValue1;
+	@Value("${registration.pending.property.name2:}")
+	private String registrationPendingPropertyName2;
+	@Value("${registration.pending.property.value2:}")
+	private String registrationPendingPropertyValue2;
+	@Value("${registration.pending.property.name3:}")
+	private String registrationPendingPropertyName3;
+	@Value("${registration.pending.property.value3:}")
+	private String registrationPendingPropertyValue3;
+	@Value("${registration.pending.property.name4:}")
+	private String registrationPendingPropertyName4;
+	@Value("${registration.pending.property.value4:}")
+	private String registrationPendingPropertyValue4;
+	@Value("${registration.pending.property.name5:}")
+	private String registrationPendingPropertyName5;
+	@Value("${registration.pending.property.value5:}")
+	private String registrationPendingPropertyValue5;
 	
 	@Value("${registration.staticPropertyMapping:false}")
 	private boolean staticPropertyMappingEnabled;
@@ -213,6 +235,30 @@ public class RegistrationModule extends AbstractSpringModule {
 	public String getRegistrationNotificationEmail() {
 		return registrationNotificationEmail;
 	}
+	
+	public void setRegistrationNotificationEmail(String email) {
+		registrationNotificationEmail = email;
+		setStringProperty("registration.notificationEmail", email, true);
+	}
+	
+	public boolean isRegistrationNotificationEmailEnabled() {
+		return registrationNotificationEmailEnabled;
+	}
+	
+	public void setRegistrationNotificationEmailEnabled(boolean enabled) {
+		String enabledStr = enabled ? "true" : "false";
+		registrationNotificationEmailEnabled = enabled;
+		setStringProperty("registration.enableNotificationEmail", enabledStr, true);
+	}
+	
+	public RegistrationPendingStatus getRegistrationPendingStatus() {
+		return RegistrationPendingStatus.valueOf(registrationPendingStatus);
+	}
+	
+	public void setRegistrationPendingStatus(RegistrationPendingStatus status) {
+		this.registrationPendingStatus = status.name();
+		setStringProperty("registration.pending.status", status.name(), true);	
+	}
 
 	/**
 	 * @return true to force acceptance of disclaimer on first login; true to skip disclaimer
@@ -251,6 +297,81 @@ public class RegistrationModule extends AbstractSpringModule {
 		setStringProperty("registration.organisation.key", key, true);
 	}
 	
+	public String getRegistrationPendingPropertyName1() {
+		return registrationPendingPropertyName1;
+	}
+
+	public void setRegistrationPendingProperty1(String propertyName, String propertyValue) {
+		this.registrationPendingPropertyName1 = propertyName;
+		this.registrationPendingPropertyValue1 = propertyValue;
+		setStringProperty("registration.pending.property.name1", propertyName, false);
+		setStringProperty("registration.pending.property.value1", propertyValue, true);
+	}
+
+	public String getRegistrationPendingPropertyValue1() {
+		return registrationPendingPropertyValue1;
+	}
+
+	public String getRegistrationPendingPropertyName2() {
+		return registrationPendingPropertyName2;
+	}
+
+	public void setRegistrationPendingProperty2(String propertyName, String propertyValue) {
+		this.registrationPendingPropertyName2 = propertyName;
+		this.registrationPendingPropertyValue2 = propertyValue;
+		setStringProperty("registration.pending.property.name2", propertyName, false);
+		setStringProperty("registration.pending.property.value2", propertyValue, true);
+	}
+
+	public String getRegistrationPendingPropertyValue2() {
+		return registrationPendingPropertyValue2;
+	}
+
+	public String getRegistrationPendingPropertyName3() {
+		return registrationPendingPropertyName3;
+	}
+
+	public void setRegistrationPendingProperty3(String propertyName, String propertyValue) {
+		this.registrationPendingPropertyName3 = propertyName;
+		this.registrationPendingPropertyValue3 = propertyValue;
+		setStringProperty("registration.pending.property.name3", propertyName, false);
+		setStringProperty("registration.pending.property.value3", propertyValue, true);
+	}
+
+	public String getRegistrationPendingPropertyValue3() {
+		return registrationPendingPropertyValue3;
+	}
+
+	public String getRegistrationPendingPropertyName4() {
+		return registrationPendingPropertyName4;
+	}
+
+	public void setRegistrationPendingProperty4(String propertyName, String propertyValue) {
+		this.registrationPendingPropertyName4 = propertyName;
+		this.registrationPendingPropertyValue4 = propertyValue;
+		setStringProperty("registration.pending.property.name4", propertyName, false);
+		setStringProperty("registration.pending.property.value4", propertyValue, true);
+	}
+
+	public String getRegistrationPendingPropertyValue4() {
+		return registrationPendingPropertyValue4;
+	}
+
+	public String getRegistrationPendingPropertyName5() {
+		return registrationPendingPropertyName5;
+	}
+
+	public void setRegistrationPendingProperty5(String propertyName, String propertyValue) {
+		this.registrationPendingPropertyName5 = propertyName;
+		this.registrationPendingPropertyValue5 = propertyValue;
+		setStringProperty("registration.pending.property.name5", propertyName, false);
+		setStringProperty("registration.pending.property.value5", propertyValue, true);
+	}
+
+	public String getRegistrationPendingPropertyValue5() {
+		return registrationPendingPropertyValue5;
+	}
+
 	@Override
 	public void init() {
 		//registration enabled/disabled
@@ -270,6 +391,56 @@ public class RegistrationModule extends AbstractSpringModule {
 		if(StringHelper.containsNonWhitespace(loginEnabledObj)) {
 			selfRegistrationLoginEnabled = "true".equals(loginEnabledObj);
 		}
+		
+		String enableNotificationEmailObj = getStringPropertyValue("registration.enableNotificationEmail", true);
+		if(StringHelper.containsNonWhitespace(enableNotificationEmailObj)) {
+			registrationNotificationEmailEnabled = "true".equals(enableNotificationEmailObj);
+		}
+		
+		String notificationEmailObj = getStringPropertyValue("registration.notificationEmail", true);
+		if(StringHelper.containsNonWhitespace(notificationEmailObj)) {
+			registrationNotificationEmail = notificationEmailObj;
+		}
+	
+		String pendingPropName1Obj = getStringPropertyValue("registration.pending.property.name1", true);
+		String pendingPropValue1Obj = getStringPropertyValue("registration.pending.property.value1", true);
+		if(StringHelper.containsNonWhitespace(pendingPropName1Obj) && StringHelper.containsNonWhitespace(pendingPropValue1Obj)) {
+			registrationPendingPropertyName1 = pendingPropName1Obj;
+			registrationPendingPropertyValue1 = pendingPropValue1Obj;
+		}
+		
+		String pendingPropName2Obj = getStringPropertyValue("registration.pending.property.name2", true);
+		String pendingPropValue2Obj = getStringPropertyValue("registration.pending.property.value2", true);
+		if(StringHelper.containsNonWhitespace(pendingPropName2Obj) && StringHelper.containsNonWhitespace(pendingPropValue2Obj)) {
+			registrationPendingPropertyName2 = pendingPropName2Obj;
+			registrationPendingPropertyValue2 = pendingPropValue2Obj;
+		}
+		
+		String pendingPropName3Obj = getStringPropertyValue("registration.pending.property.name3", true);
+		String pendingPropValue3Obj = getStringPropertyValue("registration.pending.property.value3", true);
+		if(StringHelper.containsNonWhitespace(pendingPropName3Obj) && StringHelper.containsNonWhitespace(pendingPropValue3Obj)) {
+			registrationPendingPropertyName3 = pendingPropName3Obj;
+			registrationPendingPropertyValue3 = pendingPropValue3Obj;
+		}
+
+		String pendingPropName4Obj = getStringPropertyValue("registration.pending.property.name4", true);
+		String pendingPropValue4Obj = getStringPropertyValue("registration.pending.property.value4", true);
+		if(StringHelper.containsNonWhitespace(pendingPropName4Obj) && StringHelper.containsNonWhitespace(pendingPropValue4Obj)) {
+			registrationPendingPropertyName4 = pendingPropName4Obj;
+			registrationPendingPropertyValue4 = pendingPropValue4Obj;
+		}
+		
+		String pendingPropName5Obj = getStringPropertyValue("registration.pending.property.name5", true);
+		String pendingPropValue5Obj = getStringPropertyValue("registration.pending.property.value5", true);
+		if(StringHelper.containsNonWhitespace(pendingPropName5Obj) && StringHelper.containsNonWhitespace(pendingPropValue5Obj)) {
+			registrationPendingPropertyName5 = pendingPropName5Obj;
+			registrationPendingPropertyValue5 = pendingPropValue5Obj;
+		}
+		
+		String pendingStatusObj = getStringPropertyValue("registration.pending.status", true);
+		if(StringHelper.containsNonWhitespace(pendingStatusObj)) {
+			registrationPendingStatus = pendingStatusObj;
+		}
 
 		String organisationObj = getStringPropertyValue("registration.organisation.key", false);
 		if(StringHelper.containsNonWhitespace(organisationObj)) {
diff --git a/src/main/java/org/olat/registration/RegistrationPendingStatus.java b/src/main/java/org/olat/registration/RegistrationPendingStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5c8387d678f6b259cc6f74a90ac32b754e6a2fb
--- /dev/null
+++ b/src/main/java/org/olat/registration/RegistrationPendingStatus.java
@@ -0,0 +1,34 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.registration;
+
+/**
+ * 
+ * Initial date: 14 déc. 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public enum RegistrationPendingStatus {
+	
+	active,
+	pending,
+	pendingMatchingProperties
+
+}
diff --git a/src/main/java/org/olat/registration/_content/admin.html b/src/main/java/org/olat/registration/_content/admin.html
index b2506f1a1880075f4c586537ecc6a4f5c357975a..29fc2e080de71b7765b67f6babd7364e02dbe3c6 100644
--- a/src/main/java/org/olat/registration/_content/admin.html
+++ b/src/main/java/org/olat/registration/_content/admin.html
@@ -1,5 +1,6 @@
 $r.render("settings")
 $r.render("domains")
+$r.render("propertiespending")
 $r.render("propertiesmapping")
 $r.render("remotelogin")
 $r.render("buttons")
\ No newline at end of file
diff --git a/src/main/java/org/olat/registration/_content/finish.html b/src/main/java/org/olat/registration/_content/finish.html
index 0bb38ed6a0b551818ad6754070d887fc77aab9dd..68a6160ed0e1366c8e01e587968d40d198c6d121 100644
--- a/src/main/java/org/olat/registration/_content/finish.html
+++ b/src/main/java/org/olat/registration/_content/finish.html
@@ -8,7 +8,7 @@
     	<div class="panel-heading">
       		<h4 class="panel-title">$r.translate("step5.reg.yourdata")</h4>
       	</div>
-      	<div class="panel-body">
+      	<div class="panel-body #if($r.isTrue($pending)) o_important #end">
       		<p>$text</p>
       	</div>
 		<table class="table table-bordered">
@@ -25,6 +25,8 @@
 		</table>
 	</div>
 </div>
+#if($r.isFalse($pending))
 <div class="o_button_group">
 	$r.render("loginhref")
 </div>
+#end
diff --git a/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties
index ec9f1064d28602df0644b3742b649b8a3c304c55..f9a4e7e8a4896745c46a9c1d415e4b1b6ba75324 100644
--- a/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties
@@ -10,6 +10,7 @@ admin.registration.domains=Dom\u00E4nenliste
 admin.registration.domains.desc=Die Selbtregistration kann optional auf eine oder mehrere Dom\u00E4nen eingeschr\u00E4nkt werden. Um diese Funktion zu aktivieren f\u00FCgen Sie eine Liste von Dom\u00E4nen an z.B\: openolat.com, *openolat.org, hotmail.com
 admin.registration.domains.error=Diese Dom\u00E4nen sind nicht g\u00FCltig\: {0}
 admin.registration.domains.title=Einschr\u00E4nkung auf Dom\u00E4ne
+admin.registration.pending.status=Benutzerstatus
 admin.registration.property=Benutzerattribut
 admin.registration.propertyValue=Standardwert
 admin.registration.propertyValue.error=Ung\u00FCltiger Wert
@@ -91,6 +92,21 @@ reg.notiEmail.subject=Neuer OpenOLAT-Benutzer\: {1} {2} ({0})
 reg.subject=Registrierungsschl\u00FCssel f\u00FCr OpenOLAT
 reg.wherefrom=Diese Anfrage an den Server {0} wurde am {1} \nvon der IP-Adresse {2} abgeschickt.
 registration.form.cancelled=Sie haben die Registrierung abgebrochen.
+registration.pending.notification.mail=Pending user creation notification email
+registration.pending.prop.name1=Benutzer-Attributename 1
+registration.pending.prop.name2=Benutzer-Attributename 2
+registration.pending.prop.name3=Benutzer-Attributename 3
+registration.pending.prop.name4=Benutzer-Attributename 4
+registration.pending.prop.name5=Benutzer-Attributename 5
+registration.pending.prop.value1=Benutzer-Attributewert 1 
+registration.pending.prop.value2=Benutzer-Attributewert 2
+registration.pending.prop.value3=Benutzer-Attributewert 3
+registration.pending.prop.value4=Benutzer-Attributewert 4
+registration.pending.prop.value5=Benutzer-Attributewert 5
+registration.pending.status=User state after self registration
+registration.pending.status.active=Active
+registration.pending.status.pending=H\u00E4ngig
+registration.pending.status.pending.props=H\u00E4ngig wenn ein von den folgenden Benutzerproperties stimmt
 regkey.missing=Der Registrierungsschl\u00FCssel fehlt. Fordern Sie bitte einen neuen an.
 regkey.missingentry=Dieser Registrierungsschl\u00FCssel existiert nicht. Bitte fordern Sie einen neuen an.
 remote.login.title=Loginformular in externe Webseite/CMS einbinden
@@ -109,6 +125,7 @@ step3.pw.text=Bitte beachten Sie bei der Eingabe des neuen OpenOLAT-Passwortes f
 step3.reg.text=Um die Registrierung abzuschliessen, f\u00FCllen Sie bitte das Formular mit Ihren Angaben aus.
 step4.pw.text=Sie haben Ihr OpenOLAT-Passwort neu gesetzt. 
 step4.reg.text=<b>Bitte akzeptieren Sie die Nutzungsbedingungen, bevor Sie fortfahren.</b>
+step5.reg.pending=Anmeldung ist pending.
 step5.reg.text=Sie k\u00F6nnen sich nun mit Ihrem Benutzernamen <b>{0}</b> und Passwort anmelden\:
 step5.reg.yourdata=Zusammenfassung Ihrer Angaben\:
 step.add.reg.text=In Sprachanpassungswerkzeug <strong>org.olat.registration</strong> <strong>step.add.reg.text</strong>
diff --git a/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties
index f03b08322c9e10e2afe0c12ed131d4e2b73df90a..d845de3cc28914e64a3c501ec07a5f27bafa096b 100644
--- a/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties
@@ -10,6 +10,7 @@ admin.registration.domains=List of domains
 admin.registration.domains.desc=Optionally the self registration can be limited to one or multiple domains. To activate this feature add a list of domains into the form below, e.g. \: openolat.com, *openolat.org, hotmail.com
 admin.registration.domains.error=The following domains are not valid\: {0}
 admin.registration.domains.title=Domain limitation
+admin.registration.pending.status=User status
 admin.registration.property=User property name
 admin.registration.propertyValue=User property value
 admin.registration.propertyValue.error=Invalid user property value
@@ -91,6 +92,21 @@ reg.notiEmail.subject=New OpenOLAT user\: {1} {2} ({0})
 reg.subject=Registration key for OpenOLAT
 reg.wherefrom=This registration request to the server {0} was made on {1} \nfrom the IP address {2}.
 registration.form.cancelled=You have cancelled the registration process.
+registration.pending.notification.mail=Pending user creation notification email
+registration.pending.prop.name1=User property name 1
+registration.pending.prop.name2=User property name 2
+registration.pending.prop.name3=User property name 3
+registration.pending.prop.name4=User property name 4
+registration.pending.prop.name5=User property name 5
+registration.pending.prop.value1=User property value 1
+registration.pending.prop.value2=User property value 2
+registration.pending.prop.value3=User property value 3
+registration.pending.prop.value4=User property value 4
+registration.pending.prop.value5=User property value 5
+registration.pending.status=User state after self registration
+registration.pending.status.active=Active
+registration.pending.status.pending=Pending
+registration.pending.status.pending.props=Pending if one of the following user properties matches
 regkey.missing=Registration key missing. Please ask for a new one.
 regkey.missingentry=This registration key does not exist. Please ask for another one.
 remote.login.title=Embed login form into external website/CMS
@@ -108,6 +124,7 @@ step2.reg.text=Thank you for your interest in OpenOLAT. You will receive an e-ma
 step3.pw.text=Please consider the following instructions for setting an OpenOLAT password\:
 step3.reg.text=In order to finish your registration, please fill in the form.
 step4.pw.text=You have changed your OpenOLAT password successfully.
+step5.reg.pending=Registration is pending.
 step4.reg.text=<b>Please read the terms of use before proceeding.</b>
 step5.reg.text=You can now log in with your OpenOLAT user name <b>{0}</b> and password\:
 step5.reg.yourdata=Summary of your data\: