diff --git a/src/main/java/de/thm/arsnova/controller/AuthenticationController.java b/src/main/java/de/thm/arsnova/controller/AuthenticationController.java
index 7c7df3663b54acfed83a8525134117b2375604e5..7dead0ff264aa83cea65e9f328e1cb3c89f9d57b 100644
--- a/src/main/java/de/thm/arsnova/controller/AuthenticationController.java
+++ b/src/main/java/de/thm/arsnova/controller/AuthenticationController.java
@@ -18,6 +18,7 @@
 
 package de.thm.arsnova.controller;
 
+import javax.servlet.http.HttpServletRequest;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -44,22 +45,23 @@ public class AuthenticationController {
 	}
 
 	@PostMapping("/login/registered")
-	public ClientAuthentication loginRegistered(@RequestBody final LoginCredentials loginCredentials) {
+	public ClientAuthentication loginRegistered(@RequestBody final LoginCredentials loginCredentials,
+			final HttpServletRequest request) {
 		final String loginId = loginCredentials.getLoginId().toLowerCase();
 		userService.authenticate(new UsernamePasswordAuthenticationToken(loginId, loginCredentials.getPassword()),
-				UserProfile.AuthProvider.ARSNOVA);
+				UserProfile.AuthProvider.ARSNOVA, request.getRemoteAddr());
 		return userService.getCurrentClientAuthentication();
 	}
 
 	@PostMapping("/login/guest")
-	public ClientAuthentication loginGuest() {
+	public ClientAuthentication loginGuest(final HttpServletRequest request) {
 		final ClientAuthentication currentAuthentication = userService.getCurrentClientAuthentication();
 		if (currentAuthentication != null
 				&& currentAuthentication.getAuthProvider() == UserProfile.AuthProvider.ARSNOVA_GUEST) {
 			return currentAuthentication;
 		}
 		userService.authenticate(new UsernamePasswordAuthenticationToken(null, null),
-				UserProfile.AuthProvider.ARSNOVA_GUEST);
+				UserProfile.AuthProvider.ARSNOVA_GUEST, request.getRemoteAddr());
 
 		return userService.getCurrentClientAuthentication();
 	}
diff --git a/src/main/java/de/thm/arsnova/controller/UserController.java b/src/main/java/de/thm/arsnova/controller/UserController.java
index abc74d0ce2ad0b03cdd998fb87d241559b1c79d6..f2e19777b1cfdd6bd4eb108b13a785b98d444b3d 100644
--- a/src/main/java/de/thm/arsnova/controller/UserController.java
+++ b/src/main/java/de/thm/arsnova/controller/UserController.java
@@ -19,6 +19,7 @@
 package de.thm.arsnova.controller;
 
 import com.fasterxml.jackson.annotation.JsonView;
+import javax.servlet.http.HttpServletRequest;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -104,13 +105,11 @@ public class UserController extends AbstractEntityController<UserProfile> {
 	@PostMapping(ACTIVATE_MAPPING)
 	public void activate(
 			@PathVariable final String id,
-			@RequestParam final String key) {
-		final UserProfile userProfile = userService.get(id, true);
-		if (userProfile == null || !key.equals(userProfile.getAccount().getActivationKey())) {
+			@RequestParam final String key,
+			final HttpServletRequest request) {
+		if (!userService.activateAccount(id, key, request.getRemoteAddr())) {
 			throw new BadRequestException();
 		}
-		userProfile.getAccount().setActivationKey(null);
-		userService.update(userProfile);
 	}
 
 	@PostMapping(RESET_PASSWORD_MAPPING)
diff --git a/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java b/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java
index fd52193a804f77260d518bfec4cf578e7d5ca130..75e64453cbc64c3592186b08d30f7d0d471bd003 100644
--- a/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java
+++ b/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java
@@ -133,8 +133,8 @@ public class AuthenticationController extends AbstractController {
 			final HttpServletRequest request,
 			final HttpServletResponse response
 	) throws IOException {
-		final String addr = request.getRemoteAddr();
-		if (userService.isBannedFromLogin(addr)) {
+		final String address = request.getRemoteAddr();
+		if (userService.isBannedFromLogin(address)) {
 			response.sendError(429, "Too Many Requests");
 
 			return;
@@ -144,26 +144,23 @@ public class AuthenticationController extends AbstractController {
 
 		if (registeredProperties.isEnabled() && "arsnova".equals(type)) {
 			try {
-				userService.authenticate(authRequest, UserProfile.AuthProvider.ARSNOVA);
+				userService.authenticate(authRequest, UserProfile.AuthProvider.ARSNOVA, address);
 			} catch (final AuthenticationException e) {
 				logger.info("Database authentication failed.", e);
-				userService.increaseFailedLoginCount(addr);
 				response.setStatus(HttpStatus.UNAUTHORIZED.value());
 			}
 		} else if (ldapProperties.stream().anyMatch(p -> p.isEnabled()) && "ldap".equals(type)) {
 			try {
-				userService.authenticate(authRequest, UserProfile.AuthProvider.LDAP);
+				userService.authenticate(authRequest, UserProfile.AuthProvider.LDAP, address);
 			} catch (final AuthenticationException e) {
 				logger.info("LDAP authentication failed.", e);
-				userService.increaseFailedLoginCount(addr);
 				response.setStatus(HttpStatus.UNAUTHORIZED.value());
 			}
 		} else if (guestProperties.isEnabled() && "guest".equals(type)) {
 			try {
-				userService.authenticate(authRequest, UserProfile.AuthProvider.ARSNOVA_GUEST);
+				userService.authenticate(authRequest, UserProfile.AuthProvider.ARSNOVA_GUEST, address);
 			} catch (final AuthenticationException e) {
 				logger.debug("Guest authentication failed.", e);
-				userService.increaseFailedLoginCount(addr);
 				response.setStatus(HttpStatus.UNAUTHORIZED.value());
 			}
 		} else {
diff --git a/src/main/java/de/thm/arsnova/controller/v2/UserController.java b/src/main/java/de/thm/arsnova/controller/v2/UserController.java
index aec8a783b77155788c050abaf18b72c4194ba75a..b1836860dbdc79f649886a0872ed21fc9cf32eb5 100644
--- a/src/main/java/de/thm/arsnova/controller/v2/UserController.java
+++ b/src/main/java/de/thm/arsnova/controller/v2/UserController.java
@@ -61,17 +61,13 @@ public class UserController extends AbstractController {
 	@PostMapping(value = "/{username}/activate")
 	public void activate(
 			@PathVariable final String username,
-			@RequestParam final String key, final HttpServletRequest request,
+			@RequestParam final String key,
+			final HttpServletRequest request,
 			final HttpServletResponse response) {
 		final UserProfile userProfile = userService.getByUsername(username);
-		if (null != userProfile && key.equals(userProfile.getAccount().getActivationKey())) {
-			userProfile.getAccount().setActivationKey(null);
-			userService.update(userProfile);
-
-			return;
+		if (userProfile == null || !userService.activateAccount(userProfile.getId(), key, request.getRemoteAddr())) {
+			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
 		}
-
-		response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
 	}
 
 	@DeleteMapping(value = "/{username}/")
diff --git a/src/main/java/de/thm/arsnova/service/UserService.java b/src/main/java/de/thm/arsnova/service/UserService.java
index fd09780c5488ca63640b22852e3ff3978e650860..bbfd163811c4f2dce21f2fe3f21cc035c0d97e58 100644
--- a/src/main/java/de/thm/arsnova/service/UserService.java
+++ b/src/main/java/de/thm/arsnova/service/UserService.java
@@ -69,7 +69,8 @@ public interface UserService extends EntityService<UserProfile> {
 
 	int loggedInUsers();
 
-	void authenticate(UsernamePasswordAuthenticationToken token, UserProfile.AuthProvider authProvider);
+	void authenticate(UsernamePasswordAuthenticationToken token, UserProfile.AuthProvider authProvider,
+			String clientAddress);
 
 	User loadUser(UserProfile.AuthProvider authProvider, String loginId,
 			Collection<GrantedAuthority> grantedAuthorities, boolean autoCreate) throws UsernameNotFoundException;
@@ -90,6 +91,8 @@ public interface UserService extends EntityService<UserProfile> {
 
 	void addRoomToHistory(UserProfile userProfile, Room room);
 
+	boolean activateAccount(String id, String key, String clientAddress);
+
 	void initiatePasswordReset(String username);
 
 	boolean resetPassword(UserProfile userProfile, String key, String password);
diff --git a/src/main/java/de/thm/arsnova/service/UserServiceImpl.java b/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
index 10802621170b17221dd445f9933941877c717dd9..2a93a39bf406966a400a7fd74656b2674f6d36fb 100644
--- a/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
@@ -328,7 +328,11 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 
 	@Override
 	public void authenticate(final UsernamePasswordAuthenticationToken token,
-			final UserProfile.AuthProvider authProvider) {
+			final UserProfile.AuthProvider authProvider, final String clientAddress) {
+		if (isBannedFromLogin(clientAddress)) {
+			throw new BadRequestException();
+		}
+
 		final Authentication auth;
 		switch (authProvider) {
 			case LDAP:
@@ -357,6 +361,7 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 		}
 
 		if (!auth.isAuthenticated()) {
+			increaseFailedLoginCount(clientAddress);
 			throw new BadRequestException();
 		}
 		SecurityContextHolder.getContext().setAuthentication(auth);
@@ -438,7 +443,7 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 		userProfile.setAuthProvider(UserProfile.AuthProvider.ARSNOVA);
 		userProfile.setLoginId(lcUsername);
 		account.setPassword(encodePassword(password));
-		account.setActivationKey(RandomStringUtils.randomAlphanumeric(32));
+		account.setActivationKey(RandomStringUtils.randomAlphanumeric(8));
 		userProfile.setCreationTimestamp(new Date());
 
 		/* Repository is accessed directly without EntityService to skip permission check */
@@ -462,15 +467,9 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 
 	private void sendActivationEmail(final UserProfile userProfile) {
 		final String activationKey = userProfile.getAccount().getActivationKey();
-		final String activationUrl = MessageFormat.format(
-				"{0}{1}/login?action=activate&username={3}&key={4}",
-				rootUrl,
-				customizationPath,
-				UriUtils.encodeQueryParam(userProfile.getLoginId(), "UTF-8"),
-				activationKey);
 
 		sendEmail(userProfile, registeredProperties.getRegistrationMailSubject(),
-				MessageFormat.format(registeredProperties.getRegistrationMailBody(), activationUrl, activationKey));
+				MessageFormat.format(registeredProperties.getRegistrationMailBody(), activationKey, rootUrl));
 	}
 
 	private void parseMailAddressPattern() {
@@ -544,6 +543,22 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 		}
 	}
 
+	public boolean activateAccount(final String id, final String key, final String clientAddress) {
+		if (isBannedFromLogin(clientAddress)) {
+			return false;
+		}
+		final UserProfile userProfile = get(id, true);
+		if (userProfile == null || !key.equals(userProfile.getAccount().getActivationKey())) {
+			increaseFailedLoginCount(clientAddress);
+			return false;
+		}
+
+		userProfile.getAccount().setActivationKey(null);
+		update(userProfile);
+
+		return true;
+	}
+
 	@Override
 	public void initiatePasswordReset(final String username) {
 		final UserProfile userProfile = getByUsername(username);
@@ -563,27 +578,15 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 			throw new BadRequestException();
 		}
 
-		account.setPasswordResetKey(RandomStringUtils.randomAlphanumeric(32));
+		account.setPasswordResetKey(RandomStringUtils.randomAlphanumeric(8));
 		account.setPasswordResetTime(new Date());
 
 		if (null == userRepository.save(userProfile)) {
 			logger.error("Password reset failed. {} could not be updated.", username);
 		}
 
-		final String resetPasswordUrl = MessageFormat.format(
-				"{0}{1}/login?action=resetpassword&username={3}&key={4}",
-				rootUrl,
-				customizationPath,
-				UriUtils.encodeQueryParam(userProfile.getLoginId(), "UTF-8"), account.getPasswordResetKey());
-
-		final String mailBody = MessageFormat.format(
-				registeredProperties.getResetPasswordMailBody(),
-				resetPasswordUrl,
-				account.getPasswordResetKey()
-		);
-
-		sendEmail(userProfile, registeredProperties.getResetPasswordMailSubject(),
-				MessageFormat.format(mailBody, resetPasswordUrl));
+		sendEmail(userProfile, registeredProperties.getResetPasswordMailSubject(), MessageFormat.format(
+				registeredProperties.getResetPasswordMailBody(), account.getPasswordResetKey(), rootUrl));
 	}
 
 	@Override
diff --git a/src/main/resources/config/defaults.yml b/src/main/resources/config/defaults.yml
index 0209418cfac7056ea479ad07a9048c920f797eb4..80c46a9cf875d1152e861643150e2059f3387360 100644
--- a/src/main/resources/config/defaults.yml
+++ b/src/main/resources/config/defaults.yml
@@ -107,16 +107,20 @@ arsnova:
         registration-mail-body: |-
           Welcome to ARSnova!
 
-          Please confirm your registration by visiting the following web address:
-          {0}
+          Here is the activation code you need for your first login to ARSnova:
 
-          Afterwards, you can log into ARSnova with your e-mail address and password.
+              {0}
+
+          {1}
         reset-password-mail-subject: ARSnova Password Reset
         reset-password-mail-body: |-
           You requested to reset your password.
 
-          Please follow the link below to set a new password:
-          {0}
+          Here is the confirmation code you need to set a new password:
+
+              {0}
+
+          {1}
 
       # LDAP authentication
       #