diff --git a/uffd/default_config.cfg b/uffd/default_config.cfg
index f6fd34521cc2e7e041e1a7aacd2dfbe88bb30c24..58b850123492995039bf5aca899879b6f8020b5a 100644
--- a/uffd/default_config.cfg
+++ b/uffd/default_config.cfg
@@ -12,3 +12,10 @@ ACL_LDAP_GROUP_USEREDIT="admins"
 
 ACL_ADMIN_GROUP="admin"
 ACL_SELFSERVICE_GROUP="user"
+
+MAIL_SERVER='smtp.gmail.com'
+MAIL_PORT=465
+MAIL_USERNAME='yourId@gmail.com'
+MAIL_PASSWORD='*****'
+MAIL_USE_STARTTLS=True
+MAIL_FROM_ADDRESS='foo@bar.com'
diff --git a/uffd/selfservice/templates/forgot_password.html b/uffd/selfservice/templates/forgot_password.html
new file mode 100644
index 0000000000000000000000000000000000000000..673eec16e1f368c895b5c798af94b8290cc00bcf
--- /dev/null
+++ b/uffd/selfservice/templates/forgot_password.html
@@ -0,0 +1,27 @@
+{% extends 'base.html' %}
+
+{% block body %}
+<form action="{{ url_for(".self_forgot_password") }}" method="POST">
+<div class="row mt-2 justify-content-center">
+	<div class="col-lg-6 col-md-10" style="background: #f7f7f7; box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); padding: 30px;">
+		<div class="text-center">
+			<img src="{{ url_for("static", filename="chaosknoten.png") }}" class="col-lg-8 col-md-12" >
+		</div>
+		<div class="col-12">
+			<h2 class="text-center">Forgot password</h2>
+		</div>
+		<div class="form-group col-12">
+			<label for="user-loginname">login name</label>
+			<input type="text" class="form-control" id="user-loginname" name="loginname" required="required" tabindex = "1">
+		</div>
+		<div class="form-group col-12">
+			<label for="user-mail">mail address</label>
+			<input type="text" class="form-control" id="user-mail" name="mail" required="required" tabindex = "2">
+		</div>
+		<div class="form-group col-12">
+			<button type="submit" class="btn btn-primary btn-block" tabindex = "3">Send password reset mail</button>
+		</div>
+	</div>
+</div>
+</form>
+{% endblock %}
diff --git a/uffd/selfservice/templates/passwordreset.mail.txt b/uffd/selfservice/templates/passwordreset.mail.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9560ff86ed72d01120d5f160a1480a71648b77e6
--- /dev/null
+++ b/uffd/selfservice/templates/passwordreset.mail.txt
@@ -0,0 +1,10 @@
+Hi {{ user.displayname }},
+
+you have requested a password reset.
+To reset your password, visit this url: {{ url_for('.self_token_password', token=token, _external=True) }} 
+**Please note this link is only valid for 48h**
+
+If you did not request a password reset, you do not need to do anything.
+
+Kind regards,
+uffd
diff --git a/uffd/selfservice/templates/reset_password.html b/uffd/selfservice/templates/set_password.html
similarity index 100%
rename from uffd/selfservice/templates/reset_password.html
rename to uffd/selfservice/templates/set_password.html
diff --git a/uffd/selfservice/views.py b/uffd/selfservice/views.py
index 9d745347764194e3647e5bcaff65885963b30664..ff823e40f4a764529d15a27136f27b73e2a593a3 100644
--- a/uffd/selfservice/views.py
+++ b/uffd/selfservice/views.py
@@ -1,5 +1,8 @@
 import datetime
 
+import smtplib
+from email.message import EmailMessage
+
 from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app
 
 from uffd.navbar import register_navbar
@@ -23,9 +26,22 @@ def self_index():
 @login_required()
 def self_update():
 	# TODO: actualy update the user...
-	send_passwordreset('uffdtest')
 	return 'OK', 200
 
+@bp.route("/passwordreset", methods=(['GET', 'POST']))
+@csrf_protect(blueprint=bp)
+def self_forgot_password():
+	if request.method == 'GET':
+		return render_template('forgot_password.html')
+
+	loginname = request.values['loginname']
+	mail = request.values['mail']
+	flash("We sent a mail to this users mail address if you entered the correct mail and login name combination")
+	user = User.from_ldap_dn(loginname_to_dn(loginname))
+	if user.mail == mail:
+		send_passwordreset(loginname)
+	return redirect(url_for('session.login'))
+
 @bp.route("/token/password/<token>", methods=(['POST', 'GET']))
 def self_token_password(token):
 	session = db.session
@@ -38,16 +54,16 @@ def self_token_password(token):
 		return redirect(url_for('session.login'))
 	if not 'loginname' in request.values:
 		flash('Please set a new password.')
-		return render_template('reset_password.html', token=token)
+		return render_template('set_password.html', token=token)
 	else:
 		if not request.values['loginname'] == dbtoken.loginname:
-			flash('That is not the correct login name. Please start the password reset process again')
+			flash('That is not the correct login name for this token. Your token is now invalide. Please start the password reset process again')
 			session.delete(dbtoken)
 			session.commit()
 			return redirect(url_for('session.login'))
 		if not request.values['password1']:
 			flash('Please specify a new password.')
-			return render_template('reset_password.html', token=token)
+			return render_template('set_password.html', token=token)
 		user = User.from_ldap_dn(loginname_to_dn(dbtoken.loginname))
 		user.set_password(request.values['password1'])
 		user.to_ldap()
@@ -56,8 +72,6 @@ def self_token_password(token):
 		session.commit()
 		return redirect(url_for('session.login'))
 
-
-
 def send_passwordreset(loginname):
 	session = db.session
 	expired_tokens = PasswordToken.query.filter(PasswordToken.created < (datetime.datetime.now() - datetime.timedelta(days=2))).all()
@@ -66,5 +80,21 @@ def send_passwordreset(loginname):
 	token = PasswordToken()
 	token.loginname = loginname
 	session.add(token)
-	# TODO: send mail
 	session.commit()
+
+	user = User.from_ldap_dn(loginname_to_dn(loginname))
+
+	msg = EmailMessage()
+	msg.set_content(render_template('passwordreset.mail.txt', user=user, token=token.token))
+	msg['Subject'] = 'Password reset'
+	send_mail(user.mail, msg)
+
+def send_mail(to, msg):
+	server = smtplib.SMTP(host=current_app.config['MAIL_SERVER'], port=current_app.config['MAIL_PORT'])
+	if current_app.config['MAIL_USE_STARTTLS']:
+		server.starttls()
+	server.login(current_app.config['MAIL_USERNAME'], current_app.config['MAIL_PASSWORD'])
+	msg['From'] = current_app.config['MAIL_FROM_ADDRESS']
+	msg['To'] = to
+	server.send_message(msg)
+	server.quit()
diff --git a/uffd/session/templates/login.html b/uffd/session/templates/login.html
index 3c36bc305586d73ba95d30aa67718776f5c401d3..4ca476e2161f191d0927a4ea0600b99e64a2ddb6 100644
--- a/uffd/session/templates/login.html
+++ b/uffd/session/templates/login.html
@@ -23,7 +23,7 @@
 		</div>
 		<div class="clearfix col-12">
 			<a href="#" class="float-left">Register</a>
-			<a href="#" class="float-right">Forgot Password?</a>
+			<a href="{{ url_for("selfservice.self_forgot_password") }}" class="float-right">Forgot Password?</a>
 		</div>
 	</div>
 </div>
diff --git a/uffd/session/views.py b/uffd/session/views.py
index 269c0a49a721abf6af5bcf18535b1bab529462e9..d0a06fdd2c98321be2b7d4d9153e66d2e2856898 100644
--- a/uffd/session/views.py
+++ b/uffd/session/views.py
@@ -53,7 +53,6 @@ def is_valid_session():
 	if not user:
 		return False
 	if datetime.datetime.now().timestamp() > session['logintime'] + current_app.config['SESSION_LIFETIME_SECONDS']:
-		flash('Session timed out')
 		return False
 	return True
 bp.add_app_template_global(is_valid_session)