The following scenario is a problem and it needs to be eliminated:
#1, It's totally arbitrary when I decide the code is good and when I increment the version number.
#2, The first delivery is pointless when the client rejects it before testing.
#3, I didn't want to rev the version because there are not enough digits in the version number.
#4, I delievered 2 zip files that are similar enough to be confusing. The binaries have the exact same filename. Now I don't have proof whether I made a mistake or they used the binary from the wrong delivery. Moreover, since I only delivered a Hex and not an ELF, it's way harder to do the binary anaysis.
Jenkins eliminates email deliveries. I don't deliver the binaries to the client, I publish the binaries with Jenkins. This way, there is always a latest release in 1 place. Never look back in an email or your own filesystem again. Always go to the publisher.
The better build system includes tighter integration with source control and incrementing version numbers. Definitely include some optional versioning like a build number or commit SHA, so the filename of the binary is always changing.
That mistake I made, pointed at in #4 above, was due to myself putting test code in the production build. Not unit tests, but a POST hardware test. What the client saw indicated that I forgot to remove the POST. I definitely remembered to do it, but somehow a mistake slipped in.
I could have avoided this by parameterizing the build and generating extra build outputs. There's the real final release, and then other parameterized builds like "myapp-0.0.0+WITH_POST". This way, it's impossible to make that mistake. No switching back and forth, just generate both and select one.
Combining the 2, this should guarantee that every build on Jenkins is unique and reproducible.