diff --git a/Lab4/__pycache__/database_helper.cpython-310.pyc b/Lab4/__pycache__/database_helper.cpython-310.pyc
index 39a86975cf1d2709547c7edc3fcfc7d630ba111c..f635570f53710411968225763425148b7abec8f0 100644
Binary files a/Lab4/__pycache__/database_helper.cpython-310.pyc and b/Lab4/__pycache__/database_helper.cpython-310.pyc differ
diff --git a/Lab4/__pycache__/server.cpython-310.pyc b/Lab4/__pycache__/server.cpython-310.pyc
index 32747256fc1acb196f39de31516988c4e65704be..8923e6ded4ef87e497f3fa990279cda3c78dcc4d 100644
Binary files a/Lab4/__pycache__/server.cpython-310.pyc and b/Lab4/__pycache__/server.cpython-310.pyc differ
diff --git a/Lab4/database.db b/Lab4/database.db
index 7fd372c02c76c6a5d6a8824bc576312f87bdef86..4d522693d6546cc621213a78e6a9558f282423d2 100644
Binary files a/Lab4/database.db and b/Lab4/database.db differ
diff --git a/Lab4/database_helper.py b/Lab4/database_helper.py
index 2e52d2f10967c104be861b9067c90d8ff74afe04..2b9eb1344fa8996cde47c7e1238d46e1138e45b7 100644
--- a/Lab4/database_helper.py
+++ b/Lab4/database_helper.py
@@ -173,10 +173,16 @@ def check_user_exists(email):
 
 def change_password(email, newpassword):
     try:
-        sql = "UPDATE USERS SET PASSWORD = ? WHERE EMAIL = ?;"
-        get_db().execute(sql, (newpassword, email))
-        get_db().commit()
-        return True
+        cursor = get_db().cursor()
+        cursor.execute("SELECT EMAIL FROM USERS WHERE EMAIL=?", [email])
+        exists = cursor.fetchone()
+        if exists:
+            sql = "UPDATE USERS SET PASSWORD = ? WHERE EMAIL = ?;"
+            get_db().execute(sql, (newpassword, email))
+            get_db().commit()
+            return True
+        else:
+            return False
     except:
         return False
 
diff --git a/Lab4/server.py b/Lab4/server.py
index c915e2314368c31391893cb1615e4dab4b8c3def..88f37dd51b7b930ffce393c1c7290af830a1ee18 100644
--- a/Lab4/server.py
+++ b/Lab4/server.py
@@ -1,5 +1,7 @@
-from flask import Flask, request, jsonify
+from flask import Flask, request, jsonify, render_template
 from flask_sock import Sock
+from datetime import datetime, timedelta
+from flask_mail import Mail, Message
 
 import waitress
 import database_helper
@@ -8,11 +10,25 @@ import string
 import json
 import re
 import io
+import os
+import secrets
 
 app = Flask(__name__, template_folder='static')
+app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'devkey')
+app.config['MAIL_SERVER']='sandbox.smtp.mailtrap.io'
+app.config['MAIL_PORT'] = 2525
+app.config['MAIL_USERNAME'] = 'c1159416d31517'
+app.config['MAIL_PASSWORD'] = '9971f0f667254a'
+app.config['MAIL_USE_TLS'] = True
+app.config['MAIL_USE_SSL'] = False
+app.config['RECOVERY_TOKEN_LIFETIME'] = timedelta(minutes=1)
+app.config['RECOVERY_TOKEN_LENGTH'] = 24
+
 sockets = Sock(app)
+mail = Mail(app)
 
 loggedIn_for_ws = {}
+tokens = {}
 
 @sockets.route("/profil_view")
 def socket_connection(ws):
@@ -32,6 +48,57 @@ def hello_world():
     return app.send_static_file("client.html"), 200
 
 
+@app.route('/password-recovery', methods=['GET', 'POST'])
+def password_recovery():
+    if request.method == 'POST':
+        email = request.form['email']
+        if database_helper.check_user_exists(email):
+            token = generate_recovery_token(email)
+            send_recovery_link(email, token)
+            return render_template('password_recovery_sent.html')
+        else:
+            return render_template('password_recovery_form.html', message_error="This email doesn't exist")
+    else:
+        return render_template('password_recovery_form.html')
+
+def generate_recovery_token(email):
+    token = secrets.token_hex(app.config['RECOVERY_TOKEN_LENGTH'])
+    expiration_date = datetime.utcnow() + app.config['RECOVERY_TOKEN_LIFETIME']
+    tokens[token] = {'email': email, 'expiration_date': expiration_date}
+    return token
+
+def send_recovery_link(email, token):
+    msg = Message('Twidder Password Recovery', sender='twidder@mailtrap.io', recipients=[email])
+    recovery_link = request.url_root + 'reset-password/' + token
+    msg.body = f'Click the following link to reset your Twidder password: {recovery_link}'
+    mail.send(msg)
+
+@app.route('/reset-password/<token>', methods=['GET', 'POST'])
+def reset_password(token):
+    if token not in tokens:
+        return render_template('password_recovery_form.html')
+
+    expiration_date = tokens[token]['expiration_date']
+    if datetime.utcnow() > expiration_date:
+        del tokens[token]
+        return render_template('password_recovery_form.html')
+
+    if token in tokens and request.method == 'GET':
+        return render_template('recover_password.html')
+
+    if request.method == 'POST':
+        pass1 = request.form['password1']
+        pass2 = request.form['password2']
+        email = tokens[token]['email']
+        if(len(pass1) > 5 and len(pass2) > 5) and (pass1 == pass2):
+            del tokens[token]
+            database_helper.change_password(email, pass1)
+            return render_template('client.html')
+        else:
+            return render_template('recover_password.html', message_error = "Please enter a password of 6 characters at least and enter the same passwords.")
+    else:
+        return render_template('password_recovery_form.html')
+
 @app.route("/users/sign_up", methods = ['POST'])
 def sign_up():
     data = request.get_json()
@@ -84,7 +151,10 @@ def sign_in():
 def sign_out():
     token = get_token_from_header()
     if(token != 1):
+        email = database_helper.tokenToEmail(token)
         if database_helper.removeFromLoggedInUsers(token):
+            del loggedIn_for_ws[email]
+            print("loggedIn_for_ws : ", loggedIn_for_ws)
             return "", 200
         else:
             return "", 401
diff --git a/Lab4/static/client.css b/Lab4/static/client.css
index 340dedfac6308a89436d7e28a4e2753f1d891836..879a877d07e677808d5759c87aba614d65bbee96 100644
--- a/Lab4/static/client.css
+++ b/Lab4/static/client.css
@@ -34,6 +34,12 @@ body {
     width: 600px;
 }
 
+.forgot-password {
+  position: absolute;
+  margin-top: 5px;
+  margin-left: 60px;
+}
+
 h2 {
     text-align: center;
 }
@@ -91,6 +97,11 @@ img {
     margin-top: 20px;
 }
 
+#merror {
+  color: red;
+  text-align: center;
+}
+
 #panel-default {
     background-color: darkgrey;
     border: solid black 1px;
diff --git a/Lab4/static/client.html b/Lab4/static/client.html
index dc7af93fc34f24fc170610d70eb1e48741d3f9b4..d1b693d2739491af49d02490961a2cfed5daf782 100644
--- a/Lab4/static/client.html
+++ b/Lab4/static/client.html
@@ -14,6 +14,7 @@
                     <form id="login" onsubmit="signIn(this); return false;">
                         <div><label for="email">Email</label><input class="logintexts" type="email" id="l_email" required></div>
                         <div><label for="password">Password</label><input class="logintexts" type="password" id="l_password" required></div>
+                        <div><a href="/password-recovery" class="forgot-password" ">Forgot password?</a></div>
                         <input value="Login" class="lbutton" type="submit">
                     </form>
                     <form id="signup" onsubmit="signUp(this); return false;">
diff --git a/Lab4/static/client.js b/Lab4/static/client.js
index 3bf22126ce679293c07619adb5f5eb8b334b2c69..6a21092085b0ebeffbe87d5128e831aedc59280e 100644
--- a/Lab4/static/client.js
+++ b/Lab4/static/client.js
@@ -211,6 +211,13 @@ function signIn(formData) {
 
 }
 
+function checkpass(formData) {
+  let passwords = {
+    password1 : formData.password1.value,
+    password2 : formData.password2.value
+  }
+  window.alert('test');
+}
 //---------------------------------------SIGN OUT---------------------------------------
 
 function signOut() {
@@ -511,7 +518,7 @@ function drop(e) {
   document.getElementById("drop-zone").classList.remove("hover");
   var files = e.dataTransfer.files;
   var file = files[0];
-  
+
   if (file.type.endsWith('png') || file.type.endsWith('jpeg')) {
     const formData = new FormData();
     formData.append('image', file);
@@ -542,6 +549,7 @@ function load_profilepicture() {
   var xhr = new XMLHttpRequest();
   xhr.open('GET', '/users/account/getpp/' + localStorage.getItem('reloadHome'));
   xhr.responseType = 'blob';
+  xhr.send();
   xhr.onload = function() {
     if (xhr.status === 200) {
       // Create a new image object from the blob data
@@ -550,5 +558,5 @@ function load_profilepicture() {
       img.src = window.URL.createObjectURL(blob);
     }
   };
-  xhr.send();
+
 }
diff --git a/Lab4/static/password_recovery.css b/Lab4/static/password_recovery.css
new file mode 100644
index 0000000000000000000000000000000000000000..2d724327f3a5e1e82ada45563ac92c88fa51297a
--- /dev/null
+++ b/Lab4/static/password_recovery.css
@@ -0,0 +1,34 @@
+body {
+  background-color: #0F98B7;
+}
+.container {
+  max-width: 300px;
+  margin: auto;
+}
+form {
+  background-color: #fff;
+  padding: 20px;
+  border-radius: 5px;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+}
+label {
+  font-weight: bold;
+}
+
+.form-group {
+  display: flex;
+  flex-direction: column;
+  width: 250px;
+}
+
+.form-group label {
+  text-align: left;
+}
+
+button {
+  margin-top: 5px;
+}
+
+#error {
+  color: red;
+}
diff --git a/Lab4/static/password_recovery_form.html b/Lab4/static/password_recovery_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..f4da50f02c6c06e79a3faa759302787baaa60693
--- /dev/null
+++ b/Lab4/static/password_recovery_form.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Twidder - Password Recovery</title>
+    <link href="/static/password_recovery.css" type="text/css" rel="stylesheet">
+  </head>
+  <body>
+    <div class="container">
+      <h1 class="mt-5 mb-3">Password Recovery</h1>
+      <form method="post" action="/password-recovery">
+        <div class="form-group">
+          <label for="email">Enter your email</label>
+          <input type="email" class="form-control" id="email" name="email" required>
+        </div>
+        <button type="submit" class="btn btn-primary">Send Recovery Link</button>
+        <p id="error">{{message_error}}<p>
+      </form>
+    </div>
+  </body>
+</html>
diff --git a/Lab4/static/password_recovery_sent.html b/Lab4/static/password_recovery_sent.html
new file mode 100644
index 0000000000000000000000000000000000000000..fd9e290627f1c77294b9bf2d00f9a11da91730ad
--- /dev/null
+++ b/Lab4/static/password_recovery_sent.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Twidder - Password Recovery Sent</title>
+    <link href="/static/password_recovery.css" type="text/css" rel="stylesheet">
+  </head>
+  <body>
+    <div class="container">
+      <h1 class="mt-5 mb-3">Password Recovery Sent</h1>
+      <p>An email has been sent to your email with a link to reset your password. Please check your inbox.</p>
+    </div>
+  </body>
+</html>
diff --git a/Lab4/static/recover_password.html b/Lab4/static/recover_password.html
new file mode 100644
index 0000000000000000000000000000000000000000..54e027082e9d75f1a2e7067ad356e7a1fc58d137
--- /dev/null
+++ b/Lab4/static/recover_password.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Twidder - Change Password</title>
+    <link href="/static/password_recovery.css" type="text/css" rel="stylesheet">
+  </head>
+  <body>
+    <div class="container">
+      <h1 class="mt-5 mb-3">Change password</h1>
+      <form method="post">
+        <div class="form-group">
+          <label for="password1">New password</label>
+          <input type="password" class="form-control" id="password1" name="password1" required>
+          <label for="password2" id="test">Write it again</label>
+          <input type="password" class="form-control" id="password2" name="password2" required>
+          <button type="submit" class="btn btn-primary">Change</button>
+          <p id="error">{{message_error}}<p>
+        </div>
+      </form>
+    </div>
+  </body>
+</html>