diff --git a/app/controllers/api/v1/admin/invitations_controller.rb b/app/controllers/api/v1/admin/invitations_controller.rb
index 5d022e8330e02d88bc5f1ed00dda2e191ddb163f..6aab95298cb9eee297ccac18d0b6b38111552885 100644
--- a/app/controllers/api/v1/admin/invitations_controller.rb
+++ b/app/controllers/api/v1/admin/invitations_controller.rb
@@ -39,7 +39,7 @@ module Api
         # Creates an invitation for the specified emails (comma separated) and sends them an email
         def create
           params[:invitations][:emails].split(',').each do |email|
-            invitation = Invitation.find_or_initialize_by(email:, provider: current_provider).tap do |i|
+            invitation = Invitation.find_or_initialize_by(email: email.downcase, provider: current_provider).tap do |i|
               i.updated_at = Time.zone.now
               i.save!
             end
diff --git a/app/controllers/api/v1/migrations/external_controller.rb b/app/controllers/api/v1/migrations/external_controller.rb
index f9d39c1537c419779a0679a428c2af0ea881075a..9a68ab20c882b2b3933d71fb19c3cd1cc5cf1d89 100644
--- a/app/controllers/api/v1/migrations/external_controller.rb
+++ b/app/controllers/api/v1/migrations/external_controller.rb
@@ -91,7 +91,7 @@ module Api
             return render_error(status: :bad_request, errors: 'Provider does not exist')
           end
 
-          return render_data status: :created if User.exists?(email: user_hash[:email], provider: user_hash[:provider])
+          return render_data status: :created if User.exists?(email: user_hash[:email].downcase, provider: user_hash[:provider])
 
           user_hash[:language] = I18n.default_locale if user_hash[:language].blank? || user_hash[:language] == 'default'
 
diff --git a/app/controllers/api/v1/reset_password_controller.rb b/app/controllers/api/v1/reset_password_controller.rb
index 99c7a8d30f51fbb7677f4be67a33ee52433fa46d..feea5ec0f0645c6cb9d7e2ca11ff93460134054e 100644
--- a/app/controllers/api/v1/reset_password_controller.rb
+++ b/app/controllers/api/v1/reset_password_controller.rb
@@ -30,7 +30,7 @@ module Api
         # TODO: Log events.
         return render_error unless params[:user]
 
-        user = User.find_by email: params[:user][:email]
+        user = User.find_by email: params[:user][:email].downcase
 
         # Silently fail for unfound or external users.
         return render_data status: :ok unless user && !user.external_id?
diff --git a/app/controllers/api/v1/sessions_controller.rb b/app/controllers/api/v1/sessions_controller.rb
index d764ad97f0e432f0479db7b73208778cb7cf0d2b..65a07e91255214f90cb513560989018c507307da 100644
--- a/app/controllers/api/v1/sessions_controller.rb
+++ b/app/controllers/api/v1/sessions_controller.rb
@@ -36,7 +36,8 @@ module Api
         return render_error if hcaptcha_enabled? && !verify_hcaptcha(response: params[:token])
 
         # Search for a user within the current provider and, if not found, search for a super admin within bn provider
-        user = User.find_by(email: session_params[:email], provider: current_provider) || User.find_by(email: session_params[:email], provider: 'bn')
+        user = User.find_by(email: session_params[:email].downcase, provider: current_provider) ||
+               User.find_by(email: session_params[:email].downcase, provider: 'bn')
 
         # Return an error if the user is not found
         return render_error if user.blank?
diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb
index 95b7a69e72887b5b6601fb42bc39e09e6eedbc4f..f00dd0e31dd16b4f9ce85958593b9657cca9fa03 100644
--- a/app/controllers/api/v1/users_controller.rb
+++ b/app/controllers/api/v1/users_controller.rb
@@ -169,7 +169,8 @@ module Api
         return false if create_user_params[:invite_token].blank?
 
         # Try to delete the invitation and return true if it succeeds
-        Invitation.destroy_by(email: create_user_params[:email], provider: current_provider, token: create_user_params[:invite_token]).present?
+        Invitation.destroy_by(email: create_user_params[:email].downcase, provider: current_provider,
+                              token: create_user_params[:invite_token]).present?
       end
     end
   end
diff --git a/app/controllers/external_controller.rb b/app/controllers/external_controller.rb
index b7f7a4d141a6a8eea344642a3f3ead16e4512aad..7e916805665dd76043bf564687521afe0d5e4ea4 100644
--- a/app/controllers/external_controller.rb
+++ b/app/controllers/external_controller.rb
@@ -129,7 +129,7 @@ class ExternalController < ApplicationController
     return false if token.blank?
 
     # Try to delete the invitation and return true if it succeeds
-    Invitation.destroy_by(email:, provider: current_provider, token:).present?
+    Invitation.destroy_by(email: email.downcase, provider: current_provider, token:).present?
   end
 
   def build_user_info(credentials)
diff --git a/app/services/recordings_sync.rb b/app/services/recordings_sync.rb
index af50e10bdfe4df077675df6048d0914a4fdd7ef6..bacdfd19fb22a10f49771c9b816473688179dfee 100644
--- a/app/services/recordings_sync.rb
+++ b/app/services/recordings_sync.rb
@@ -23,9 +23,9 @@ class RecordingsSync
   end
 
   def call
-    recordings = @room.recordings
-    Format.where(recordings:).delete_all
-    recordings.delete_all
+    room_recordings = @room.recordings
+    Format.where(recording: room_recordings).delete_all
+    room_recordings.delete_all
 
     recordings = BigBlueButtonApi.new(provider: @provider).get_recordings(meeting_ids: @room.meeting_id)
     recordings[:recordings].each do |recording|
diff --git a/db/data/20231030185844_lowercase_emails.rb b/db/data/20231030185844_lowercase_emails.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fbe41a00bb47f6521391c4202bab13a378f8247e
--- /dev/null
+++ b/db/data/20231030185844_lowercase_emails.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class LowercaseEmails < ActiveRecord::Migration[7.1]
+  def up
+    User.all.find_each(batch_size: 250) do |user|
+      downcase = user.email.downcase
+      next if user.email == downcase
+
+      user.update(email: downcase)
+    end
+  end
+
+  def down
+    raise ActiveRecord::IrreversibleMigration
+  end
+end
diff --git a/db/data_schema.rb b/db/data_schema.rb
index 4013193075f193cdffdb13d2a63d4a24a2e41b34..5e92e7bfecaa7864ee567eb7417175dc02cf50e6 100644
--- a/db/data_schema.rb
+++ b/db/data_schema.rb
@@ -1 +1 @@
-DataMigrate::Data.define(version: 20230228193705)
+DataMigrate::Data.define(version: 20231030185844)
diff --git a/db/schema.rb b/db/schema.rb
index f0760fed4a74d8baa006ee16b0effe7db9a6f718..9cd0b8c6630d604d83f4884bb9004df77d1cfc47 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.0].define(version: 2023_07_05_183747) do
+ActiveRecord::Schema[7.1].define(version: 2023_07_05_183747) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
   enable_extension "plpgsql"