Hi Mark,
The loop you mentioned I missed actually (and in the process may have found a bug in hyperkitty).
After running the code in the mailman shell:
for mbr in m.members.members: if mbr.address is None: print('user: {}, user.addresses: {}'.format(mbr.user, mbr.user.addresses))
I didn't get any result in the test list, presumably because I had fixed that in the db directly. However on running it on the main migrated list, I found two entries with the problem - perhaps not surprisingly exactly the same member as had caused the problem with the test list. Once I fixed it (adding a preferred address id to the user table), the result was no more entries were returned. I also tried it on another migrated list and it came 'clean' as well.
As for the potential bug in hyperkitty, I have been referencing the hyperkitty version of this thread as I was working the problem, and while I faintly remember seeing the loop in the email on my phone, when I was referencing the hyperkitty version of your email it was not there - even when expanding the quoted text....perhaps you see the same thing via hyperkitty? Essentially it removed part of the message that was intended to be seen.
Regarding the email duplicate issue - thanks for pointing me to that posting - glad to know it isn't just me!
Cheers,
Duane