The QR code one mail app drew and the other left blank
The receipt email carried its QR code as inline vector art. One mail client drew it; the one most guests use drew nothing. A PNG is what every client draws.
The receipt email ends with a QR code: scan it and the receipt opens on your phone, with the itemised lines and the VAT breakdown, ready to forward to whoever pays expenses. The code was drawn as vector art embedded straight into the email, which is sharp at any size and needs no second download. In one mail client it looked exactly like the design. In the one most guests read their receipts in, it was a blank square.
Why it shipped
Because the person who built it checked it in the client they use. That client draws inline vector images. The other strips any image whose address is the image itself, as a security measure, and draws no vector art at all, inline or linked. So the email was tested, it passed, and it was broken for most of the people it went to. A test that runs in one environment proves one environment.
The one shape every client draws
A PNG, fetched from our own address, under the receipt’s own token so only the person holding the receipt link can ask for it. The worker had no PNG writer, so we wrote one: one grey channel, uncompressed blocks, about ninety lines, no dependency to mirror. A QR code is a few thousand bytes of two values; real compression would not pay for itself. The image is cached as immutable, because a receipt’s code never changes, and the first request after the receipt is written is the only one that does any work.
The page and the PDF keep the vector version, where it is sharper and where every renderer draws it. Only the email changed, because only the email had the problem.
The test that round-trips the bytes
A PNG writer with a wrong checksum produces a file that some decoders accept and others reject, which is the same bug in a different coat. So the test does not inspect the bytes; it decodes the file with an independent decoder and compares every pixel against the code’s own module grid. Dark where the code is dark, light where it is light, with the quiet zone all round, at two scales.
If an email looks right on your phone, open it on the other kind of phone before you call it done. The client you do not use is the one your customers do.