diff --git a/src/matrixmessageprocessor.ts b/src/matrixmessageprocessor.ts
index 3f5aa9f88c9ebfc8dd308e3228e6275dc3e6daca..124978d7689fb22620c6ac60d9bf76e8d7217b70 100644
--- a/src/matrixmessageprocessor.ts
+++ b/src/matrixmessageprocessor.ts
@@ -24,6 +24,7 @@ import { Client as MatrixClient } from "matrix-js-sdk";
 const MIN_NAME_LENGTH = 2;
 const MAX_NAME_LENGTH = 32;
 const MATRIX_TO_LINK = "https://matrix.to/#/";
+const DEFAULT_ROOM_NOTIFY_POWER_LEVEL = 50;
 
 export interface IMatrixMessageProcessorParams {
     displayname?: string;
@@ -75,24 +76,34 @@ export class MatrixMessageProcessor {
         return reply;
     }
 
+    private async canNotifyRoom() {
+        if (!this.params || !this.params.mxClient || !this.params.roomId || !this.params.userId) {
+            return false;
+        }
+
+        const res: IMatrixEvent = await this.params.mxClient.getStateEvent(
+            this.params.roomId, "m.room.power_levels");
+
+        // Some rooms may not have notifications.room set if the value hasn't
+        // been changed from the default. If so, use our hardcoded power level.
+        const requiredPowerLevel = res && res.notifications && res.notifications.room
+            ? res.notifications.room
+            : DEFAULT_ROOM_NOTIFY_POWER_LEVEL;
+
+        return res && res.users
+            && res.users[this.params.userId] !== undefined
+            && res.users[this.params.userId] >= requiredPowerLevel;
+    }
+
     private async escapeDiscord(msg: string): Promise<string> {
         // \u200B is the zero-width space --> they still look the same but don't mention
         msg = msg.replace(/@everyone/g, "@\u200Beveryone");
         msg = msg.replace(/@here/g, "@\u200Bhere");
 
-        if (msg.includes("@room") && this.params && this.params.mxClient && this.params.roomId && this.params.userId) {
-            // let's check for more complex logic if @room should be replaced
-            const res: IMatrixEvent = await this.params.mxClient.getStateEvent(
-                this.params.roomId, "m.room.power_levels");
-            if (
-                res && res.users
-                && res.users[this.params.userId] !== undefined
-                && res.notifications
-                && res.notifications.room !== undefined
-                && res.users[this.params.userId] >= res.notifications.room
-            ) {
-                msg = msg.replace(/@room/g, "@here");
-            }
+        // Check the Matrix permissions to see if this user has the required
+        // power level to notify with @room; if so, replace it with @here.
+        if (msg.includes("@room") && await this.canNotifyRoom()) {
+            msg = msg.replace(/@room/g, "@here");
         }
         const escapeChars = ["\\", "*", "_", "~", "`", "|"];
         msg = msg.split(" ").map((s) => {
diff --git a/test/test_matrixmessageprocessor.ts b/test/test_matrixmessageprocessor.ts
index 66fced8ee3fe2e238c8ea451dd0aa92924981316..99626917d695d263732a2c80b0f32adcb2edddf8 100644
--- a/test/test_matrixmessageprocessor.ts
+++ b/test/test_matrixmessageprocessor.ts
@@ -29,23 +29,6 @@ import { MatrixMessageProcessor } from "../src/matrixmessageprocessor";
 
 const expect = Chai.expect;
 
-const mxClient = {
-    getStateEvent: async (roomId, stateType, _) => {
-        if (stateType === "m.room.power_levels") {
-            return {
-                notifications: {
-                    room: 50,
-                },
-                users: {
-                    "@nopower:localhost": 0,
-                    "@power:localhost": 100,
-                },
-            };
-        }
-        return null;
-    },
-};
-
 const bot = {
     GetEmojiByMxc: async (mxc: string): Promise<DbEmoji> => {
         if (mxc === "mxc://real_emote:localhost") {
@@ -377,6 +360,47 @@ code
         });
     });
     describe("FormatMessage / formatted_body / matrix", () => {
+        /**
+         * Returns a mocked matrix client that mocks the m.room.power_levels
+         * event to test @room notifications.
+         *
+         * @param roomNotificationLevel the power level required to @room
+         * (if undefined, does not include notifications.room in
+         * m.room.power_levels)
+         */
+        function getMxClient(roomNotificationLevel?: number) {
+            return {
+                getStateEvent: async (roomId, stateType, _) => {
+                    if (stateType === "m.room.power_levels") {
+                        return {
+                            // Only include notifications.room when
+                            // roomNotificationLevel is undefined
+                            ...roomNotificationLevel !== undefined && {
+                                notifications: {
+                                    room: roomNotificationLevel,
+                                },
+                            },
+                            users: {
+                                "@nopower:localhost": 0,
+                                "@power:localhost": 100,
+                            },
+                        };
+                    }
+                    return null;
+                },
+            };
+        }
+
+        /**
+         * Explicit power level required to notify @room.
+         *
+         * Essentially, we want to test two code paths - one where the explicit
+         * power level is set and one where it isn't, to see if the bridge can
+         * fall back to a default level (of 50). This is the explicit value we
+         * will set.
+         */
+        const ROOM_NOTIFICATION_LEVEL = 50;
+
         it("escapes @everyone", async () => {
             const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
@@ -395,24 +419,46 @@ code
             const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getPlainMessage("hey @room");
-            const params = {
-                mxClient,
+            let params = {
+                mxClient: getMxClient(ROOM_NOTIFICATION_LEVEL),
                 roomId: "!123456:localhost",
                 userId: "@power:localhost",
             };
-            const result = await mp.FormatMessage(msg, guild as any, params as any);
+            let result = await mp.FormatMessage(msg, guild as any, params as any);
+            expect(result).is.equal("hey @here");
+
+            // Test again using an unset notifications.room value in
+            // m.room.power_levels, to ensure it falls back to a default
+            // requirement.
+            params = {
+                mxClient: getMxClient(),
+                roomId: "!123456:localhost",
+                userId: "@power:localhost",
+            };
+            result = await mp.FormatMessage(msg, guild as any, params as any);
             expect(result).is.equal("hey @here");
         });
         it("ignores @room to @here conversion, if insufficient power", async () => {
             const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getPlainMessage("hey @room");
-            const params = {
-                mxClient,
+            let params = {
+                mxClient: getMxClient(ROOM_NOTIFICATION_LEVEL),
                 roomId: "!123456:localhost",
                 userId: "@nopower:localhost",
             };
-            const result = await mp.FormatMessage(msg, guild as any, params as any);
+            let result = await mp.FormatMessage(msg, guild as any, params as any);
+            expect(result).is.equal("hey @room");
+
+            // Test again using an unset notifications.room value in
+            // m.room.power_levels, to ensure it falls back to a default
+            // requirement.
+            params = {
+                mxClient: getMxClient(),
+                roomId: "!123456:localhost",
+                userId: "@nopower:localhost",
+            };
+            result = await mp.FormatMessage(msg, guild as any, params as any);
             expect(result).is.equal("hey @room");
         });
         it("handles /me for normal names", async () => {