diff --git a/src/bot.ts b/src/bot.ts
index e482314ed6dfe148da99ccfc845ea6cc0f4c034b..09d87e118cb9df5a8d000aaeab6b26cbef326e9e 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -26,7 +26,7 @@ import {
     DiscordMessageProcessorOpts,
     DiscordMessageProcessorResult,
 } from "./discordmessageprocessor";
-import { MatrixEventProcessor, MatrixEventProcessorOpts } from "./matrixeventprocessor";
+import { MatrixEventProcessor, MatrixEventProcessorOpts, IMatrixEventProcessorResult } from "./matrixeventprocessor";
 import { PresenceHandler } from "./presencehandler";
 import { Provisioner } from "./provisioner";
 import { UserSyncroniser } from "./usersyncroniser";
@@ -345,53 +345,23 @@ export class DiscordBot {
         }
     }
 
-    public async ProcessMatrixStateEvent(event: IMatrixEvent): Promise<void> {
-        log.verbose(`Got state event from ${event.room_id} ${event.type}`);
-        const channel = await this.GetChannelFromRoomId(event.room_id) as Discord.TextChannel;
-        const msg = this.mxEventProcessor.StateEventToMessage(event, channel);
+    public async sendAsBot(msg: string, channel: Discord.TextChannel, event: IMatrixEvent): Promise<void> {
         if (!msg) {
             return;
         }
-        let res = await channel.send(msg);
-        if (!Array.isArray(res)) {
-            res = [res];
-        }
-        await Util.AsyncForEach(res, async (m: Discord.Message) => {
-            log.verbose("Sent (state msg) ", m.id);
-            this.sentMessages.push(m.id);
-            this.lastEventIds[event.room_id] = event.event_id;
-            const evt = new DbEvent();
-            evt.MatrixId = `${event.event_id};${event.room_id}`;
-            evt.DiscordId = m.id;
-            evt.GuildId = channel.guild.id;
-            evt.ChannelId = channel.id;
-            await this.store.Insert(evt);
-        });
-        if (!this.config.bridge.disableReadReceipts) {
-            try {
-                await this.bridge.getIntent().sendReadReceipt(event.room_id, event.event_id);
-            } catch (err) {
-                log.error(`Failed to send read receipt for ${event}. `, err);
-            }
-        }
+        const res = await channel.send(msg);
+        await this.StoreMessagesSent(res, channel, event);
     }
 
-    public async ProcessMatrixMsgEvent(event: IMatrixEvent, guildId: string, channelId: string): Promise<void> {
-        const mxClient = this.bridge.getClientFactory().getClientAs();
-        log.verbose(`Looking up ${guildId}_${channelId}`);
-        const result = await this.LookupRoom(guildId, channelId, event.sender);
-        const chan = result.channel;
-        const botUser = result.botUser;
-
-        const embedSet = await this.mxEventProcessor.EventToEmbed(event, chan);
+    public async send(
+        embedSet: IMatrixEventProcessorResult,
+        opts: Discord.MessageOptions,
+        roomLookup: ChannelLookupResult,
+        event: IMatrixEvent,
+    ): Promise<void> {
+        const chan = roomLookup.channel;
+        const botUser = roomLookup.botUser;
         const embed = embedSet.messageEmbed;
-        const opts: Discord.MessageOptions = {};
-        const file = await this.mxEventProcessor.HandleAttachment(event, mxClient);
-        if (typeof(file) === "string") {
-            embed.description += " " + file;
-        } else {
-            opts.file = file;
-        }
 
         let msg: Discord.Message | null | (Discord.Message | null)[] = null;
         let hook: Discord.Webhook | undefined;
@@ -429,32 +399,10 @@ export class DiscordBot {
                 opts.embed = embed;
                 msg = await chan.send("", opts);
             }
+            await this.StoreMessagesSent(msg, chan, event);
         } catch (err) {
             log.error("Couldn't send message. ", err);
         }
-        if (!Array.isArray(msg)) {
-            msg = [msg];
-        }
-        await Util.AsyncForEach(msg, async (m: Discord.Message) => {
-            log.verbose("Sent ", m.id);
-            this.sentMessages.push(m.id);
-            this.lastEventIds[event.room_id] = event.event_id;
-            const evt = new DbEvent();
-            evt.MatrixId = `${event.event_id};${event.room_id}`;
-            evt.DiscordId = m.id;
-            // Webhooks don't send guild info.
-            evt.GuildId = guildId;
-            evt.ChannelId = channelId;
-            await this.store.Insert(evt);
-        });
-        if (!this.config.bridge.disableReadReceipts) {
-            try {
-                await this.bridge.getIntent().sendReadReceipt(event.room_id, event.event_id);
-            } catch (err) {
-                log.error(`Failed to send read receipt for ${event}. `, err);
-            }
-        }
-        return;
     }
 
     public async ProcessMatrixRedact(event: IMatrixEvent) {
@@ -919,4 +867,32 @@ export class DiscordBot {
             }
         }
     }
+
+    private async StoreMessagesSent(
+        msg: Discord.Message | null | (Discord.Message | null)[],
+        chan: Discord.TextChannel,
+        event: IMatrixEvent,
+    ) {
+        if (!Array.isArray(msg)) {
+            msg = [msg];
+        }
+        await Util.AsyncForEach(msg, async (m: Discord.Message) => {
+            if (!m) {
+                return;
+            }
+            log.verbose("Sent ", m.id);
+            this.sentMessages.push(m.id);
+            this.lastEventIds[event.room_id] = event.event_id;
+            try {
+                const evt = new DbEvent();
+                evt.MatrixId = `${event.event_id};${event.room_id}`;
+                evt.DiscordId = m.id;
+                evt.GuildId = chan.guild.id;
+                evt.ChannelId = chan.id;
+                await this.store.Insert(evt);
+            } catch (err) {
+                log.error(`Failed to insert sent event (${event.event_id};${event.room_id}) into store`, err);
+            }
+        });
+    }
 }
diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts
index dfab2e6488d995112de5a8008111d42eea42f609..b0489e02a16bacae2e4eaa6c598ebd389c3ae0d4 100644
--- a/src/matrixeventprocessor.ts
+++ b/src/matrixeventprocessor.ts
@@ -100,7 +100,7 @@ export class MatrixEventProcessor {
             }
             return;
         } else if (["m.room.member", "m.room.name", "m.room.topic"].includes(event.type)) {
-            await this.discord.ProcessMatrixStateEvent(event);
+            await this.ProcessStateEvent(event);
             return;
         } else if (event.type === "m.room.redaction" && context.rooms.remote) {
             await this.discord.ProcessMatrixRedact(event);
@@ -116,7 +116,7 @@ export class MatrixEventProcessor {
             } else if (context.rooms.remote) {
                 const srvChanPair = context.rooms.remote.roomId.substr("_discord".length).split("_", ROOM_NAME_PARTS);
                 try {
-                    await this.discord.ProcessMatrixMsgEvent(event, srvChanPair[0], srvChanPair[1]);
+                    await this.ProcessMsgEvent(event, srvChanPair[0], srvChanPair[1]);
                     return;
                 } catch (err) {
                     log.warn("There was an error sending a matrix event", err);
@@ -155,7 +155,30 @@ export class MatrixEventProcessor {
         await this.bridge.getRoomStore().removeEntriesByMatrixRoomId(roomId);
     }
 
-    public StateEventToMessage(event: IMatrixEvent, channel: Discord.TextChannel): string | undefined {
+    public async ProcessMsgEvent(event: IMatrixEvent, guildId: string, channelId: string) {
+        const mxClient = this.bridge.getClientFactory().getClientAs();
+        log.verbose(`Looking up ${guildId}_${channelId}`);
+        const roomLookup = await this.discord.LookupRoom(guildId, channelId, event.sender);
+        const chan = roomLookup.channel;
+        const botUser = roomLookup.botUser;
+
+        const embedSet = await this.EventToEmbed(event, chan);
+        const opts: Discord.MessageOptions = {};
+        const file = await this.HandleAttachment(event, mxClient);
+        if (typeof(file) === "string") {
+            embedSet.messageEmbed.description += " " + file;
+        } else {
+            opts.file = file;
+        }
+
+        await this.discord.send(embedSet, opts, roomLookup, event);
+        await this.sendReadReceipt(event);
+    }
+
+    public async ProcessStateEvent(event: IMatrixEvent) {
+        log.verbose(`Got state event from ${event.room_id} ${event.type}`);
+        const channel = await this.discord.GetChannelFromRoomId(event.room_id) as Discord.TextChannel;
+
         const SUPPORTED_EVENTS = ["m.room.member", "m.room.name", "m.room.topic"];
         if (!SUPPORTED_EVENTS.includes(event.type)) {
             log.verbose(`${event.event_id} ${event.type} is not displayable.`);
@@ -198,7 +221,8 @@ export class MatrixEventProcessor {
         }
 
         msg += " on Matrix.";
-        return msg;
+        await this.discord.sendAsBot(msg, channel, event);
+        await this.sendReadReceipt(event);
     }
 
     public async EventToEmbed(
@@ -342,6 +366,16 @@ export class MatrixEventProcessor {
         return embed;
     }
 
+    private async sendReadReceipt(event: IMatrixEvent) {
+        if (!this.config.bridge.disableReadReceipts) {
+            try {
+                await this.bridge.getIntent().sendReadReceipt(event.room_id, event.event_id);
+            } catch (err) {
+                log.error(`Failed to send read receipt for ${event}. `, err);
+            }
+        }
+    }
+
     private HasAttachment(event: IMatrixEvent): boolean {
         if (!event.content) {
             event.content = {};