I think the code in SessionTimeoutWatcher() is bad. It looks like it will always cut off any connection that is active when collectCount >= collectInterval, roughly once every five minutes after Papercut starts. Likely this is very uncommon, as you need
a connection to stay active for at least five minutes to be sure to hit this, and you need it to remain active for several seconds at a time to ever hit it.
This line appears to have the wrong comparison:
// If they have been idle for too long, disconnect them
if (DateTime.Now < this._connections[key].LastActivity.AddMinutes(20))
We probably want DateTime.Now to be later than 20 minutes after the last activity. Wouldn't that be a greater than sign?