Fair question. I could only recommend maintaining an extra field for administration purpose of the previous attachment names. So, each time your workflow runs (e.g., after a trigger on an update event) you get the current attachment names and compare that with the content of the PreviousAttachmentNames field.
Then - before you complete the workflow - write the current attachment names string into that special field for the next time you want to compare.
But here is an important note: make sure you exclude this update of the PreviousAttachmentNames field from the trigger condition. Otherwise, you might create an infinite loop.
My first thinking was 'good idea' but then I realized that I am running into a chicken / egg issue than.
My variable vPrevAttachmentCount is initially 0
I have a field PrevAttCount (default is 0)
vPrevAttachmentCount will be set by determining the field value from PrevAttCount.
My variable vCurrentAttCount is determined by Workflow action 'Get attachment names' [Number of attachments returned]
Let's say the update condition is logically set to vPrevAttachmentCount != vCurrentAttCount.
At some point I need to assign the new value to the field PrevAttCount which is causing the update event again.
At a later point of time a user changed some field values, but not the attachments. As vPrevAttachmentCount and vCurrentAttCount are having the same value now, the Workflow will not run my business logic.
If I change the update condition to logically vPrevAttachmentCount == vCurrentAttCount and a user changes field values and attachments at a later point of time, the Workflow will not run my business logic.
So, I think there is no way out and I have to live with a second unwanted mail...
Thanks anyway.