You are comparing "instances" to "visits".. that could be accounting for a lot of the discrepancy...
Let's look at a simple example... all from your email:
1. User opens email (there may be multiple links in that email)
2. User clicks on link 1 (marketing channel is set for the visit, instance of the utm is also tracked)
3. User goes back to that email, clicks on the next link
4. User is still part of the same visit, those numbers won't increase, but you will be tracking a new UTM instance
If you want compare visits to visits, you could create a segment that looks for "Campaign Query String Instances" to exist, then stack that with Visits metric
As @yuhuisg mentioned, the user may be performing multiple actions in the same visit... email links, social media, natural search, etc... your Marketing Channel, will default to the last touch.
On top of that, your Marketing Channels have a longer expiry (it could be a week, it could be 30 days, it all depends on your set up.. you can also control which Marketing Channels don't overwrite previous values... by default, direct traffic is set to not override, but if your Email channel was set up like that (you would have to check), it might in theory not be set correctly...

The reasoning for direct and internal to not override is that you want your actioned campaigns and drivers to maintain their values, that would included emails... but it's worth checking to be sure this is set up correctly)