diff --git a/CHANGES.md b/CHANGES.md
index 412d32a0a1..75b11bdbd4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -7,6 +7,7 @@ Features:
 Improvements:
  - Add unread indent on room list (#485)
  - Message Editing: Update notifications (#128)
+ - Remove any notification of a redacted event (#563)
 
 Other changes:
  -
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt
index 28fcff0c76..05396cb219 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt
@@ -43,6 +43,7 @@ interface PushRuleService {
     interface PushRuleListener {
         fun onMatchRule(event: Event, actions: List<Action>)
         fun onRoomLeft(roomId: String)
+        fun onEventRedacted(redactedEventId: String)
         fun batchFinish()
     }
 }
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt
index 83b89701b3..7cccd0dc3e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt
@@ -132,6 +132,16 @@ internal class DefaultPushRuleService @Inject constructor(
         }
     }
 
+    fun dispatchRedactedEventId(redactedEventId: String) {
+        try {
+            listeners.forEach {
+                it.onEventRedacted(redactedEventId)
+            }
+        } catch (e: Throwable) {
+            Timber.e(e, "Error while dispatching room left")
+        }
+    }
+
     fun dispatchFinish() {
         try {
             listeners.forEach {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/ProcessEventForPushTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/ProcessEventForPushTask.kt
index a434c6e950..064f1e3f46 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/ProcessEventForPushTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/ProcessEventForPushTask.kt
@@ -78,6 +78,25 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
                 defaultPushRuleService.dispatchBing(event, it)
             }
         }
+
+        val allRedactedEvents = params.syncResponse.join
+                .map { entries ->
+                    entries.value.timeline?.events?.filter {
+                        it.type == EventType.REDACTION
+                    }
+                            .orEmpty()
+                            .mapNotNull { it.redacts }
+                }
+                .fold(emptyList<String>(), { acc, next ->
+                    acc + next
+                })
+
+        Timber.v("[PushRules] Found ${allRedactedEvents.size} redacted events")
+
+        allRedactedEvents.forEach { redactedEventId ->
+            defaultPushRuleService.dispatchRedactedEventId(redactedEventId)
+        }
+
         defaultPushRuleService.dispatchFinish()
     }
 
diff --git a/vector/src/gplay/java/im/vector/riotx/gplay/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/gplay/java/im/vector/riotx/gplay/push/fcm/VectorFirebaseMessagingService.kt
index dcb228cfbd..cde848ea41 100755
--- a/vector/src/gplay/java/im/vector/riotx/gplay/push/fcm/VectorFirebaseMessagingService.kt
+++ b/vector/src/gplay/java/im/vector/riotx/gplay/push/fcm/VectorFirebaseMessagingService.kt
@@ -196,7 +196,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
         // This ID can and should be used to detect duplicate notification requests.
         val eventId = data["event_id"] ?: return //Just ignore
 
-
         val eventType = data["type"]
         if (eventType == null) {
             //Just add a generic unknown event
@@ -214,10 +213,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
             )
             notificationDrawerManager.onNotifiableEventReceived(simpleNotifiableEvent)
             notificationDrawerManager.refreshNotificationDrawer()
-
-            return
         } else {
-
             val event = parseEvent(data) ?: return
 
             val notifiableEvent = notifiableEventResolver.resolveEvent(event, session)
@@ -228,8 +224,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
                     Timber.e("--> ${event}")
                 }
             } else {
-
-
                 if (notifiableEvent is NotifiableMessageEvent) {
                     if (TextUtils.isEmpty(notifiableEvent.senderName)) {
                         notifiableEvent.senderName = data["sender_display_name"]
@@ -246,7 +240,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
                 notificationDrawerManager.refreshNotificationDrawer()
             }
         }
-
     }
 
     private fun findRoomNameBestEffort(data: Map<String, String>, session: Session?): String? {
diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/InviteNotifiableEvent.kt b/vector/src/main/java/im/vector/riotx/features/notifications/InviteNotifiableEvent.kt
index 10add07a66..5ecc66ffd4 100644
--- a/vector/src/main/java/im/vector/riotx/features/notifications/InviteNotifiableEvent.kt
+++ b/vector/src/main/java/im/vector/riotx/features/notifications/InviteNotifiableEvent.kt
@@ -32,6 +32,7 @@ data class InviteNotifiableEvent(
         override var isPushGatewayEvent: Boolean = false) : NotifiableEvent {
 
     override var hasBeenDisplayed: Boolean = false
+    override var isRedacted: Boolean = false
     override var lockScreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
 
 }
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableEvent.kt b/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableEvent.kt
index bc9c711d67..1603ea5f00 100644
--- a/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableEvent.kt
+++ b/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableEvent.kt
@@ -31,6 +31,7 @@ interface NotifiableEvent : Serializable {
     // Compat: Only for android <7, for newer version the sound is defined in the channel
     var soundName: String?
     var hasBeenDisplayed: Boolean
+    var isRedacted: Boolean
     //Used to know if event should be replaced with the one coming from eventstream
     var isPushGatewayEvent: Boolean
 }
diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableMessageEvent.kt b/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableMessageEvent.kt
index 36af131130..5a3e989f18 100644
--- a/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableMessageEvent.kt
+++ b/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableMessageEvent.kt
@@ -36,6 +36,7 @@ data class NotifiableMessageEvent(
     override var soundName: String? = null
     override var lockScreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
     override var hasBeenDisplayed: Boolean = false
+    override var isRedacted: Boolean = false
 
     var roomAvatarPath: String? = null
     var senderAvatarPath: String? = null
diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/riotx/features/notifications/NotificationDrawerManager.kt
index 3ea4c970a0..da2fd5c91a 100644
--- a/vector/src/main/java/im/vector/riotx/features/notifications/NotificationDrawerManager.kt
+++ b/vector/src/main/java/im/vector/riotx/features/notifications/NotificationDrawerManager.kt
@@ -15,7 +15,6 @@
  */
 package im.vector.riotx.features.notifications
 
-import android.app.Notification
 import android.content.Context
 import android.graphics.Bitmap
 import android.os.Handler
@@ -96,7 +95,6 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
                     notifiableEvent.noisy = false
                     eventList.remove(existing)
                     eventList.add(notifiableEvent)
-
                 } else {
                     //keep the existing one, do not replace
                 }
@@ -127,6 +125,15 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
         }
     }
 
+    fun onEventRedacted(eventId: String) {
+        synchronized(eventList) {
+            eventList.filter { it.eventId == eventId }.map { notifiableEvent ->
+                notifiableEvent.isRedacted = true
+                notifiableEvent.hasBeenDisplayed = false
+            }
+        }
+    }
+
     /**
     Clear all known events and refresh the notification drawer
      */
@@ -215,20 +222,15 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
             val summaryInboxStyle = NotificationCompat.InboxStyle()
 
             //group events by room to create a single MessagingStyle notif
-            val roomIdToEventMap: MutableMap<String, ArrayList<NotifiableMessageEvent>> = HashMap()
-            val simpleEvents: ArrayList<NotifiableEvent> = ArrayList()
-            val notifications: ArrayList<Notification> = ArrayList()
+            val roomIdToEventMap: MutableMap<String, MutableList<NotifiableMessageEvent>> = LinkedHashMap()
+            val simpleEvents: MutableList<NotifiableEvent> = ArrayList()
 
             val eventIterator = eventList.listIterator()
             while (eventIterator.hasNext()) {
                 val event = eventIterator.next()
                 if (event is NotifiableMessageEvent) {
                     val roomId = event.roomId
-                    var roomEvents = roomIdToEventMap[roomId]
-                    if (roomEvents == null) {
-                        roomEvents = ArrayList()
-                        roomIdToEventMap[roomId] = roomEvents
-                    }
+                    val roomEvents = roomIdToEventMap.getOrPut(roomId) { ArrayList() }
 
                     if (shouldIgnoreMessageEventInRoom(roomId) || outdatedDetector?.isMessageOutdated(event) == true) {
                         //forget this event
@@ -246,10 +248,10 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
 
             var globalLastMessageTimestamp = 0L
 
-            //events have been grouped
+            //events have been grouped by roomId
             for ((roomId, events) in roomIdToEventMap) {
-
-                if (events.isEmpty()) {
+                // Build the notification for the room
+                if (events.isEmpty() || events.all { it.isRedacted }) {
                     //Just clear this notification
                     Timber.v("%%%%%%%% REFRESH NOTIFICATION DRAWER $roomId has no more events")
                     NotificationUtils.cancelNotificationMessage(context, roomId, ROOM_MESSAGES_NOTIFICATION_ID)
@@ -280,7 +282,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
 
                 for (event in events) {
                     //if all events in this room have already been displayed there is no need to update it
-                    if (!event.hasBeenDisplayed) {
+                    if (!event.hasBeenDisplayed && !event.isRedacted) {
                         roomEventGroupInfo.shouldBing = roomEventGroupInfo.shouldBing || event.noisy
                         roomEventGroupInfo.customSound = event.soundName
                     }
@@ -296,7 +298,9 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
                         style.addMessage(context.getString(R.string.notification_inline_reply_failed), event.timestamp, senderPerson)
                         roomEventGroupInfo.hasSmartReplyError = true
                     } else {
-                        style.addMessage(event.body, event.timestamp, senderPerson)
+                        if (!event.isRedacted) {
+                            style.addMessage(event.body, event.timestamp, senderPerson)
+                        }
                     }
                     event.hasBeenDisplayed = true //we can consider it as displayed
 
@@ -356,7 +360,6 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
                             myUserDisplayName)
                             ?.let {
                                 //is there an id for this room?
-                                notifications.add(it)
                                 NotificationUtils.showNotificationMessage(context, roomId, ROOM_MESSAGES_NOTIFICATION_ID, it)
                             }
                     hasNewEvent = true
@@ -372,7 +375,6 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
                 //We build a simple event
                 if (firstTime || !event.hasBeenDisplayed) {
                     NotificationUtils.buildSimpleEventNotification(context, vectorPreferences, event, null, session.myUserId)?.let {
-                        notifications.add(it)
                         NotificationUtils.showNotificationMessage(context, event.eventId, ROOM_EVENT_NOTIFICATION_ID, it)
                         event.hasBeenDisplayed = true //we can consider it as displayed
                         hasNewEvent = true
@@ -396,7 +398,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
             // To ensure the best experience on all devices and versions, always include a group summary when you create a group
             // https://developer.android.com/training/notify-user/group
 
-            if (eventList.isEmpty()) {
+            if (eventList.isEmpty() || eventList.all { it.isRedacted }) {
                 NotificationUtils.cancelNotificationMessage(context, null, SUMMARY_NOTIFICATION_ID)
             } else {
                 val nbEvents = roomIdToEventMap.size + simpleEvents.size
@@ -443,12 +445,11 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
         }
     }
 
-    private fun getRoomBitmap(events: ArrayList<NotifiableMessageEvent>): Bitmap? {
+    private fun getRoomBitmap(events: List<NotifiableMessageEvent>): Bitmap? {
         if (events.isEmpty()) return null
 
         //Use the last event (most recent?)
-        val roomAvatarPath = events.last().roomAvatarPath
-                ?: events.last().senderAvatarPath
+        val roomAvatarPath = events.last().roomAvatarPath ?: events.last().senderAvatarPath
 
         return bitmapLoader.getRoomBitmap(roomAvatarPath)
     }
@@ -476,14 +477,14 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
         }
     }
 
-    private fun loadEventInfo(): ArrayList<NotifiableEvent> {
+    private fun loadEventInfo(): MutableList<NotifiableEvent> {
         try {
             val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
             if (file.exists()) {
                 FileInputStream(file).use {
                     val events: ArrayList<NotifiableEvent>? = activeSessionHolder.getSafeActiveSession()?.loadSecureSecret(it, KEY_ALIAS_SECRET_STORAGE)
                     if (events != null) {
-                        return ArrayList(events.mapNotNull { it as? NotifiableEvent })
+                        return events.toMutableList()
                     }
                 }
             }
diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/PushRuleTriggerListener.kt b/vector/src/main/java/im/vector/riotx/features/notifications/PushRuleTriggerListener.kt
index 555c8737c5..6711d57a22 100644
--- a/vector/src/main/java/im/vector/riotx/features/notifications/PushRuleTriggerListener.kt
+++ b/vector/src/main/java/im/vector/riotx/features/notifications/PushRuleTriggerListener.kt
@@ -60,6 +60,10 @@ class PushRuleTriggerListener @Inject constructor(
         notificationDrawerManager.clearMessageEventOfRoom(roomId)
     }
 
+    override fun onEventRedacted(redactedEventId: String) {
+        notificationDrawerManager.onEventRedacted(redactedEventId)
+    }
+
     override fun batchFinish() {
         notificationDrawerManager.refreshNotificationDrawer()
     }
diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/SimpleNotifiableEvent.kt b/vector/src/main/java/im/vector/riotx/features/notifications/SimpleNotifiableEvent.kt
index abd7b706bc..66779cfe9a 100644
--- a/vector/src/main/java/im/vector/riotx/features/notifications/SimpleNotifiableEvent.kt
+++ b/vector/src/main/java/im/vector/riotx/features/notifications/SimpleNotifiableEvent.kt
@@ -30,6 +30,7 @@ data class SimpleNotifiableEvent(
         override var isPushGatewayEvent: Boolean = false) : NotifiableEvent {
 
     override var hasBeenDisplayed: Boolean = false
+    override var isRedacted: Boolean = false
     override var lockScreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
 
 }