IMAGE BASE64 TOOL● Browser-local

IMAGE UTILITY / 05

Embed images in email

Three test emails, one inbox, the delivered HTML read back line by line. One client was tested. Where a question went untested, this page says so instead of filling the gap.

Gmail's web client loaded every inline image that arrived as a Content-ID part, and it displayed the image that arrived as an external URL. That is what three messages showed. The thing most "embed an image in email" advice is really about — a data: URI sitting in the body — was not tested here, because the only sending channel available rewrites an inline image into a cid: part before the message leaves.

Send path / messageGmail web, as receivedPhone
Mail connector — image inline in the bodyLoaded
Image loaded. It renders as a small white square, so no pattern is visible against the white background.
Not checked
No phone access.
Mail connector — image as an external URLDisplayed
The Google logo was visible.
Not checked
No phone access.
Mail connector — inline in the body and in the signatureLoaded
Both loaded. Same white square, no visible pattern.
Not checked
No phone access.
Any send path outside the connectorNot sent
No authorised sending channel was found, so no message left this way.
Not checked
No phone access.

Read that as four rows of what happened, not four rows of what always happens: one client, one inbox, three messages, and one row that is a "not sent" rather than a result. The delivered HTML is copied out below, unreworded.

What was sent, and what came back

Three messages went to a single inbox, each carrying the same small image, and each was opened in Gmail's web client. The three send paths were an image placed inline in the body; an image referenced by an external URL; and an image placed inline in the body and inline in the signature. All three arrived. The fourth row of the table is a row of nothing: the only authorised sending channel on this machine was the mail connector, and it offers no way to hand it arbitrary raw MIME, so no message left by any other path and there is no independent control to compare against.

Below is the HTML of those messages as received, copied without rewording.

The delivered HTML, copied verbatim

<img alt="INLINE-BODY" width="32" height="32" src="cid:ii_1a11c3243ae1d9bf4561">
<img alt="EXTERNAL-BODY" width="32" height="32" src="https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png">
<main><img alt="INLINE-BODY" width="32" height="32" src="cid:ii_1a11c325e691d9bf4561"></main>
<footer id="signature"><p>Test signature</p><img alt="INLINE-SIGNATURE" width="32" height="32" src="cid:ii_1a11c325e69156a76642"></footer>

Four lines, from three messages. The first is the body image of the first message. The second is the external-URL image. The third and fourth are the body and the signature image of the third message. Nothing was edited out of them; the only change is that the angle brackets are escaped so they display as text.

What those four lines establish

An image "embedded" through the connector leaves as a cid: part

The inline image in the delivered HTML is src="cid:ii_1a11c3243ae1d9bf4561" — a Content-ID reference to a MIME part carried alongside the message, not a data: URI inlined in the body. That is a fact about this one sending path, and it is the reason the fourth row of the table is empty: whatever goes in, cid: is what comes out here, so this route cannot produce the test that would settle the data: question.

The external URL came through untouched

The second line still points at https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png. The sending path did not rewrite it, wrap it, or strip it, and the client displayed it. As a control that matters more than the inline result does: it shows the reader was willing to fetch and draw an image in this message, so "the inline image appeared" is not the client being generous about everything.

Each inline image got its own identifier, and the identifiers are not random-looking

The three Content-IDs are ii_1a11c3243ae1d9bf4561, ii_1a11c325e691d9bf4561 and ii_1a11c325e69156a76642. All three are ii_ followed by twenty hex characters, and the last eight characters are not unique: two of the three end in d9bf4561, and two of the three start their hex run with 1a11c325e691. Splitting the twenty characters into twelve and eight, the trailing eight are shared by the two body images and the leading twelve are shared by the two images that travelled in the same message. Whether the trailing eight follow the image file and the leading twelve follow the message is a reading of three samples, and this test did not record which image file went into which message, so the page will not claim what either half is derived from. What it will say is that the identifier is not a fresh random string per image.

What a 32 × 32 white square can and cannot prove

The probe image was 32 × 32 and renders white. On a white message background that is close to the worst possible test subject, and it caps what the result is worth. It can prove that the image was fetched and laid out: the element kept its declared width and height, no broken-image state appeared, and the alt text was not shown in place of the image. It cannot prove that the right pixels arrived. A solid white square is indistinguishable from a blank or corrupted square of the same size, so nothing on this page should be read as a statement about image fidelity. A next run would need a large, high-contrast, non-white image before "it loaded" could be upgraded to "it loaded correctly".

The question this test did not answer

Whether a data: URI survives a trip through email is the question the phrase "embed an image in email" usually points at, and this page does not answer it. There are three places a data: URI could be changed, and the test could not separate them: the sending client could rewrite it into a cid: part before sending, the sending client could drop it outright, or a receiving client could refuse to render it. Separating those needs one message sent as raw MIME from a channel that does not touch the markup, alongside the same markup sent through the connector. Only the connector was available. No message was sent any other way. So the honest entry is "not tested", not "usually stripped" and not "usually works".

Where the rest of the picture lives

This page is only about what a mail client did with what arrived. Two neighbouring questions are on other pages and are not repeated here. Whether inlining an image is worth the bytes at all, with the threshold worked out from measurement, is Base64 encode image. Whether a string you already hold is intact or damaged is Base64 to image. Which container to save a decoded image in, and what each container costs, is Base64 to PNG. If all you want is the encoded string or the file back, the converter is on the home page.

How the test was run

Three messages, one recipient — the same mailbox the messages were sent from — and one client, Gmail's web client, where each message was opened and its source read. Every inline image in the set was supplied through the mail connector's own editor; the external image was supplied as a URL. The phone column is empty because no phone was available to open the mailbox on, and that is written as "not checked" rather than left to be inferred. No second client, no second inbox and no second sending path were used, so nothing here generalises past Gmail's web client on one account. The identifiers quoted above are the ones in the received messages; they are reproduced exactly as they appeared.