diff --git a/changelog.d/18073.bugfix b/changelog.d/18073.bugfix
new file mode 100644
index 0000000000000000000000000000000000000000..eeb56a7a618952fe3f3b67ab78aa8379b8779019
--- /dev/null
+++ b/changelog.d/18073.bugfix
@@ -0,0 +1 @@
+Deactivated users will no longer automatically accept an invite when `auto_accept_invites` is enabled.
\ No newline at end of file
diff --git a/synapse/events/auto_accept_invites.py b/synapse/events/auto_accept_invites.py
index d88ec51d9d14c4707a36c8c4b06b23e08829e5c2..4295107c47c160450a22e7f091d11b66fb845b2b 100644
--- a/synapse/events/auto_accept_invites.py
+++ b/synapse/events/auto_accept_invites.py
@@ -66,49 +66,66 @@ class InviteAutoAccepter:
             event: The incoming event.
         """
         # Check if the event is an invite for a local user.
-        is_invite_for_local_user = (
-            event.type == EventTypes.Member
-            and event.is_state()
-            and event.membership == Membership.INVITE
-            and self._api.is_mine(event.state_key)
-        )
+        if (
+            event.type != EventTypes.Member
+            or event.is_state() is False
+            or event.membership != Membership.INVITE
+            or self._api.is_mine(event.state_key) is False
+        ):
+            return
 
         # Only accept invites for direct messages if the configuration mandates it.
         is_direct_message = event.content.get("is_direct", False)
-        is_allowed_by_direct_message_rules = (
-            not self._config.accept_invites_only_for_direct_messages
-            or is_direct_message is True
-        )
+        if (
+            self._config.accept_invites_only_for_direct_messages
+            and is_direct_message is False
+        ):
+            return
 
         # Only accept invites from remote users if the configuration mandates it.
         is_from_local_user = self._api.is_mine(event.sender)
-        is_allowed_by_local_user_rules = (
-            not self._config.accept_invites_only_from_local_users
-            or is_from_local_user is True
-        )
-
         if (
-            is_invite_for_local_user
-            and is_allowed_by_direct_message_rules
-            and is_allowed_by_local_user_rules
+            self._config.accept_invites_only_from_local_users
+            and is_from_local_user is False
         ):
-            # Make the user join the room. We run this as a background process to circumvent a race condition
-            # that occurs when responding to invites over federation (see https://github.com/matrix-org/synapse-auto-accept-invite/issues/12)
-            run_as_background_process(
-                "retry_make_join",
-                self._retry_make_join,
-                event.state_key,
-                event.state_key,
-                event.room_id,
-                "join",
-                bg_start_span=False,
-            )
+            return
 
-            if is_direct_message:
-                # Mark this room as a direct message!
-                await self._mark_room_as_direct_message(
-                    event.state_key, event.sender, event.room_id
-                )
+        # Check the user is activated.
+        recipient = await self._api.get_userinfo_by_id(event.state_key)
+
+        # Ignore if the user doesn't exist.
+        if recipient is None:
+            return
+
+        # Never accept invites for deactivated users.
+        if recipient.is_deactivated:
+            return
+
+        # Never accept invites for suspended users.
+        if recipient.suspended:
+            return
+
+        # Never accept invites for locked users.
+        if recipient.locked:
+            return
+
+        # Make the user join the room. We run this as a background process to circumvent a race condition
+        # that occurs when responding to invites over federation (see https://github.com/matrix-org/synapse-auto-accept-invite/issues/12)
+        run_as_background_process(
+            "retry_make_join",
+            self._retry_make_join,
+            event.state_key,
+            event.state_key,
+            event.room_id,
+            "join",
+            bg_start_span=False,
+        )
+
+        if is_direct_message:
+            # Mark this room as a direct message!
+            await self._mark_room_as_direct_message(
+                event.state_key, event.sender, event.room_id
+            )
 
     async def _mark_room_as_direct_message(
         self, user_id: str, dm_user_id: str, room_id: str
diff --git a/tests/events/test_auto_accept_invites.py b/tests/events/test_auto_accept_invites.py
index 7fb4d4fa902fbc44febf3e74189fc60aab7e2abd..d4e87b1b7f7ad80666a340cf3e2dbb257836ba43 100644
--- a/tests/events/test_auto_accept_invites.py
+++ b/tests/events/test_auto_accept_invites.py
@@ -39,7 +39,7 @@ from synapse.module_api import ModuleApi
 from synapse.rest import admin
 from synapse.rest.client import login, room
 from synapse.server import HomeServer
-from synapse.types import StreamToken, create_requester
+from synapse.types import StreamToken, UserID, UserInfo, create_requester
 from synapse.util import Clock
 
 from tests.handlers.test_sync import generate_sync_config
@@ -349,6 +349,169 @@ class AutoAcceptInvitesTestCase(FederatingHomeserverTestCase):
             join_updates, _ = sync_join(self, invited_user_id)
             self.assertEqual(len(join_updates), 0)
 
+    @override_config(
+        {
+            "auto_accept_invites": {
+                "enabled": True,
+            },
+        }
+    )
+    async def test_ignore_invite_for_missing_user(self) -> None:
+        """Tests that receiving an invite for a missing user is ignored."""
+        inviting_user_id = self.register_user("inviter", "pass")
+        inviting_user_tok = self.login("inviter", "pass")
+
+        # A local user who receives an invite
+        invited_user_id = "@fake:" + self.hs.config.server.server_name
+
+        # Create a room and send an invite to the other user
+        room_id = self.helper.create_room_as(
+            inviting_user_id,
+            tok=inviting_user_tok,
+        )
+
+        self.helper.invite(
+            room_id,
+            inviting_user_id,
+            invited_user_id,
+            tok=inviting_user_tok,
+        )
+
+        join_updates, _ = sync_join(self, inviting_user_id)
+        # Assert that the last event in the room was not a member event for the target user.
+        self.assertEqual(
+            join_updates[0].timeline.events[-1].content["membership"], "invite"
+        )
+
+    @override_config(
+        {
+            "auto_accept_invites": {
+                "enabled": True,
+            },
+        }
+    )
+    async def test_ignore_invite_for_deactivated_user(self) -> None:
+        """Tests that receiving an invite for a deactivated user is ignored."""
+        inviting_user_id = self.register_user("inviter", "pass", admin=True)
+        inviting_user_tok = self.login("inviter", "pass")
+
+        # A local user who receives an invite
+        invited_user_id = self.register_user("invitee", "pass")
+
+        # Create a room and send an invite to the other user
+        room_id = self.helper.create_room_as(
+            inviting_user_id,
+            tok=inviting_user_tok,
+        )
+
+        channel = self.make_request(
+            "PUT",
+            "/_synapse/admin/v2/users/%s" % invited_user_id,
+            {"deactivated": True},
+            access_token=inviting_user_tok,
+        )
+
+        assert channel.code == 200
+
+        self.helper.invite(
+            room_id,
+            inviting_user_id,
+            invited_user_id,
+            tok=inviting_user_tok,
+        )
+
+        join_updates, b = sync_join(self, inviting_user_id)
+        # Assert that the last event in the room was not a member event for the target user.
+        self.assertEqual(
+            join_updates[0].timeline.events[-1].content["membership"], "invite"
+        )
+
+    @override_config(
+        {
+            "auto_accept_invites": {
+                "enabled": True,
+            },
+        }
+    )
+    async def test_ignore_invite_for_suspended_user(self) -> None:
+        """Tests that receiving an invite for a suspended user is ignored."""
+        inviting_user_id = self.register_user("inviter", "pass", admin=True)
+        inviting_user_tok = self.login("inviter", "pass")
+
+        # A local user who receives an invite
+        invited_user_id = self.register_user("invitee", "pass")
+
+        # Create a room and send an invite to the other user
+        room_id = self.helper.create_room_as(
+            inviting_user_id,
+            tok=inviting_user_tok,
+        )
+
+        channel = self.make_request(
+            "PUT",
+            f"/_synapse/admin/v1/suspend/{invited_user_id}",
+            {"suspend": True},
+            access_token=inviting_user_tok,
+        )
+
+        assert channel.code == 200
+
+        self.helper.invite(
+            room_id,
+            inviting_user_id,
+            invited_user_id,
+            tok=inviting_user_tok,
+        )
+
+        join_updates, b = sync_join(self, inviting_user_id)
+        # Assert that the last event in the room was not a member event for the target user.
+        self.assertEqual(
+            join_updates[0].timeline.events[-1].content["membership"], "invite"
+        )
+
+    @override_config(
+        {
+            "auto_accept_invites": {
+                "enabled": True,
+            },
+        }
+    )
+    async def test_ignore_invite_for_locked_user(self) -> None:
+        """Tests that receiving an invite for a suspended user is ignored."""
+        inviting_user_id = self.register_user("inviter", "pass", admin=True)
+        inviting_user_tok = self.login("inviter", "pass")
+
+        # A local user who receives an invite
+        invited_user_id = self.register_user("invitee", "pass")
+
+        # Create a room and send an invite to the other user
+        room_id = self.helper.create_room_as(
+            inviting_user_id,
+            tok=inviting_user_tok,
+        )
+
+        channel = self.make_request(
+            "PUT",
+            f"/_synapse/admin/v2/users/{invited_user_id}",
+            {"locked": True},
+            access_token=inviting_user_tok,
+        )
+
+        assert channel.code == 200
+
+        self.helper.invite(
+            room_id,
+            inviting_user_id,
+            invited_user_id,
+            tok=inviting_user_tok,
+        )
+
+        join_updates, b = sync_join(self, inviting_user_id)
+        # Assert that the last event in the room was not a member event for the target user.
+        self.assertEqual(
+            join_updates[0].timeline.events[-1].content["membership"], "invite"
+        )
+
 
 _request_key = 0
 
@@ -647,6 +810,22 @@ def create_module(
     module_api.is_mine.side_effect = lambda a: a.split(":")[1] == "test"
     module_api.worker_name = worker_name
     module_api.sleep.return_value = make_multiple_awaitable(None)
+    module_api.get_userinfo_by_id.return_value = UserInfo(
+        user_id=UserID.from_string("@user:test"),
+        is_admin=False,
+        is_guest=False,
+        consent_server_notice_sent=None,
+        consent_ts=None,
+        consent_version=None,
+        appservice_id=None,
+        creation_ts=0,
+        user_type=None,
+        is_deactivated=False,
+        locked=False,
+        is_shadow_banned=False,
+        approved=True,
+        suspended=False,
+    )
 
     if config_override is None:
         config_override = {}