Does Email Strip EXIF Data? We Built the Messages and Read the Bytes Back

Short answer: no. Sending a JPEG as a normal email attachment does not strip EXIF. The metadata is still there, byte for byte. MIME’s transfer encoding is defined to be reversible: RFC 2045 §6.2 requires the decoder to restore “the original sequence of octets which was encoded”. Base64 is a byte-to-ASCII representation, not an image operation, so it never opens the JPEG and never looks at the EXIF block. In our local test, an attachment sent through a real MIME message came back with the same 201,441 bytes, the same 14 EXIF fields, the same GPS block, and the same XMP and IPTC segments.

The thing that actually removes EXIF is re-encoding the image before you attach it — a client that resizes, compresses or “optimises” the photo. That is the same mechanism we found for WhatsApp and Telegram, and it has nothing to do with email itself. We built and parsed real MIME messages locally for this test; we did not send mail through Gmail, Outlook or any provider, so provider-side behaviour is explicitly outside what we measured.

What we tested, what we documented, and what we could not test

This article separates three kinds of claim. Keeping them apart is the whole point.

Documented. We fetched and quote four primary sources, all linked below: RFC 2045 (MIME Part One), RFC 2183 (Content-Disposition), Gmail’s official attachment help page and the Python email.message documentation. Every quoted sentence on this page was read from those documents.

Measured. Every number in the results table came from e18_local_test.py, run on this machine with Python 3.13, Pillow 12.3.0, piexif 1.1.3 and the Python standard library email package. We constructed real MIME messages, serialised them to bytes, parsed them back, extracted the attachment payload and compared it byte for byte against the source file. This part is a genuine local measurement, not an inference from documentation.

Not tested. We did not send an email through any provider, did not receive one, did not log into a mail client, and did not inspect what a server does in transit. So we make no claim about Gmail’s, Outlook’s or any provider’s server-side handling, about mail gateways that rewrite attachments, or about what a specific client’s “insert photo” button does before it hands bytes to MIME. Where this page discusses those, it is labelled as inference.

That last boundary matters. Earlier articles in this series had to work from documentation because we could not run the platform. Email is different: MIME is a published, implementable protocol, so the core question is testable without an account.

RFC 2045: the transfer encoding is required to be reversible

The single most important sentence for this question is in §6.2 of RFC 2045. It defines what a Content-Transfer-Encoding is allowed to be:

“The transformation part of any Content-Transfer-Encodings specifies, either explicitly or implicitly, a single, well-defined decoding algorithm, which for any sequence of encoded octets either transforms it to the original sequence of octets which was encoded, or shows that it is illegal as an encoded sequence.”

In other words, the standard does not permit a transfer encoding to quietly alter the payload. Decoding must give back the original bytes. EXIF, GPS, XMP and IPTC are just bytes inside the JPEG file; if the whole file comes back unchanged, all of them come back unchanged.

§6.8 describes the base64 encoding that essentially every binary attachment uses: “The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable”, and “the encoded data are consistently only about 33 percent larger than the unencoded data”. The mechanism is purely arithmetic: “The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters.” Three input bytes become four ASCII characters; no JPEG decoder is involved.

§6.2 also explains why base64 is the practical choice. The labels 7bit, 8bit and binary “all mean that the identity (i.e. NO) encoding transformation has been performed”, but the RFC states plainly that “there are no circumstances in which the “binary” Content-Transfer-Encoding is actually valid in Internet mail”. Binary image data therefore gets base64-encoded for transport. Our measurement below confirms the Python standard library does exactly that by default.

Inference, stated as such: because the standard requires byte reversibility and base64 performs no image decoding, a compliant attachment path cannot strip EXIF as a side effect. That is an inference from the specification; the byte-for-byte result in the next sections is the measurement that backs it up.

Attachment or inline: the difference is presentation, not bytes

People often assume that dragging a picture into the message body is a different kind of transfer from adding it as a file. At the MIME layer it is not. RFC 2183 defines the two Content-Disposition values purely in terms of how a mail client should present the part:

“A bodypart should be marked `inline’ if it is intended to be displayed automatically upon display of the message.” (§2.1)

“Bodyparts can be designated `attachment’ to indicate that they are separate from the main body of the mail message, and that their display should not be automatic…” (§2.2)

The RFC introduces the header as a way to “convey presentational information”. It does not describe a transformation of the body data. The Python docs likewise say add_attachment() “can be used both for explicit attachments (Content-Disposition: attachment) and inline attachments (Content-Disposition: inline)”. That documentation does not state which transfer encoding a binary payload gets, so we measured it rather than quoting a claim it never makes.

Our two base64 paths differed only in that header and in the extra HTML part carrying cid:photo1. Both delivered the identical 201,441-byte payload with identical SHA-256 prefix 838b01285920d96a. All 14 EXIF fields, the GPS block, XMP and IPTC survived in both.

Inference: when a mail app offers “insert photo” alongside “attach file”, any difference in metadata would come from what the app does to the image before building the MIME message, not from Content-Disposition. We did not test any app’s insert flow.

What Gmail's own help page says, and what it does not say

We read Gmail’s official help page “Send attachments with your Gmail message” directly. It documents size limits, not metadata:

“For personal Gmail accounts, the limit is 25 MB.”

“If your total attachment size is greater than the limit, Gmail automatically removes the attachment and adds it as a Google Drive link in the email.”

It also says “Add an image by dragging it directly into the compose window”, which is the inline path discussed above.

The page does not contain the words EXIF, metadata, compression or original quality, and it makes no statement about whether an attached file is altered. We are reporting that absence, not reading a conclusion into it: an absent statement is not evidence that stripping does or does not happen. It simply means the help page gives us nothing to cite on the subject.

One documented path change is worth knowing: above 25 MB the attachment is replaced with a Drive link. At that point the image is no longer an email attachment at all, and the MIME analysis on this page no longer applies. That is a size rule, not a metadata rule.

Our measurement setup

All numbers below are from e18_local_test.py, run locally on 2026-11-04. The script and its raw output (e18_test/e18_results.json, plus the generated .eml files and extracted attachments) are on this machine, so the whole test is reproducible.

Source file. An 800×600 JPEG, 201,441 bytes, built with Pillow. We injected 14 EXIF fields including a GPS block and deliberately set Orientation = 6. We then appended an independent APP1/XMP segment and an APP13/IPTC segment, so the file carries three separate APP markers (0xE1 EXIF, 0xE1 XMP, 0xED IPTC). That matters: it lets us tell “EXIF survived” apart from “the whole file survived”.

Procedure. For each path we built a real multipart/mixed or multipart/related message with email.mime, serialised it with as_bytes(policy=SMTP), parsed it back with BytesParser, extracted the image part with get_payload(decode=True), then compared SHA-256, counted EXIF fields, checked for GPS and scanned the APP segments for XMP and IPTC bytes. This is a genuine round trip through a serialised message, not a call to an encoder and decoder back to back.

Paths. P0 uses whatever transfer encoding the standard library picks by default; P1 explicitly uses base64 with Content-Disposition: attachment; P2 uses base64 with Content-Disposition: inline and a Content-ID; P3 uses quoted-printable; P4 uses 8bit; P5 re-encodes the JPEG first (Pillow decode → JPEG quality 85, no explicit EXIF) and then attaches it with base64, as a control.

Results: six paths, byte for byte

Every row is a locally measured result. “Identical” means the extracted attachment was byte-for-byte equal to the 201,441-byte source file.

PathCTE seenDispositionAttachment bytesEXIF fieldsGPSXMPIPTCIdentical to source
Source file——201,44114yesyesyes—
P0 Python defaultbase64attachment201,44114yesyesyesyes
P1 base64 attachmentbase64attachment201,44114yesyesyesyes
P2 base64 inlinebase64inline201,44114yesyesyesyes
P3 quoted-printablequoted-printableattachment203,05114yesyesnono
P4 8bit8bitattachment203,05114yesyesnono
P5 re-encoded, then attachedbase64attachment111,8290nononono

The three base64 paths returned SHA-256 prefix 838b01285920d96a, identical to the source. P0 also answers the “what does a normal library actually do” question: the standard library picked base64 without being told to. Mail size grew from 201,441 bytes to 276,322 bytes (a ratio of 1.3717), close to the “about 33 percent larger” figure in RFC 2045 §6.8 — the small excess is the headers and the text part.

The compressed control P5 is the only path where EXIF disappeared: 0 fields, no GPS, no XMP, no IPTC, and the pixel hash changed. It was still delivered through base64, perfectly intact — intact as the already-stripped file. The metadata was gone before MIME saw it.

The one thing that actually strips EXIF is re-encoding

This series keeps arriving at the same variable. Across four different pipelines, metadata survives or dies depending on one question: did the image get decoded and re-encoded?

The unified finding is this: transport is not the variable. A single decode-and-re-encode step is. Which is why “does email strip EXIF” is slightly the wrong question — the useful question is whether your mail client re-encoded the photo before attaching it. We cannot answer that for any specific client, because we did not test any client.

The quoted-printable / 8bit trap: a file can open while its bytes have changed

Our P3 and P4 rows are the most interesting result, and the easiest to misread. Both produced a 203,051-byte attachment — 1,610 bytes larger than the source — with EXIF still reporting 14 fields, GPS still present, XMP still present, but IPTC gone. The JPEG still opened. If you only checked “can I see the photo and does it have EXIF”, you would call this a pass.

The 1,610 bytes have an exact explanation. The source JPEG contains 1,092 bare LF bytes and 518 bare CR bytes — 1,610 in total — inside its compressed scan data. Under these line-oriented transfer encodings, each of those was normalised to a CRLF pair, adding one byte per occurrence; the 518 bare CR bytes additionally came back as LF, which is the 518 equal-length 0x0D → 0x0A differences we counted after collapsing CRLF back to LF. Compressed image data is arbitrary binary; rewriting bytes inside it changes the file even when a tolerant decoder still renders the picture.

RFC 2045 §6.7 anticipates exactly this. Its “WARNING TO IMPLEMENTORS” reads: “If binary data is encoded in quoted-printable, care must be taken to encode CR and LF characters as “=0D” and “=0A”, respectively. In particular, a CRLF sequence in binary data should be encoded as “=0D=0A”. Otherwise, if CRLF were represented as a hard line break, it might be incorrectly decoded on platforms with different line break conventions.” The same section advises that “A higher level of confidence is offered by the base64 Content-Transfer-Encoding” and, where line-break alterations would corrupt data, “it is probably more sensible to use the base64 encoding rather than the quoted-printable encoding”.

§2.8 defines 8bit data as short lines where “CR (decimal value 13) and LF (decimal value 10) octets only occur as part of CRLF line separation sequences”. A JPEG does not satisfy that, and §6.2 forbids labelling non-line-oriented unencoded data as anything other than binary. So P3 and P4 are deliberately non-compliant labelings of binary data; we included them to show what breaks, not to suggest real mail clients do this.

Scope of this result, stated plainly: the byte rewriting we observed is how Python’s BytesParser handled those two labelings in our test harness. It is a measurement about this implementation, not a claim about every mail client, gateway or server. The general point it does support is methodological: “the file opens” is not proof that metadata is intact. Only a byte-level comparison is.

So does email strip EXIF? The answer with its honest edges

For the MIME attachment path we tested: no. A base64-encoded JPEG attachment came back byte-for-byte identical, with all 14 EXIF fields, GPS, XMP and IPTC intact, whether it was labelled attachment or inline. That is a measurement, and it follows directly from a standard that requires reversible decoders.

The honest edges are where we stop measuring and start listing unknowns:

So the practical statement is narrow and defensible: email transport, as specified and as measured here, does not strip EXIF. If EXIF is missing from a photo someone emailed you, look for a re-encoding step before or after the mail, not inside MIME. That is an inference about where to look, not a claim that we observed it in any particular product.

What to actually do about it

If you want to keep the metadata: attach the original file rather than a resized copy, and avoid any client-side “compress” or “optimise” option. After the recipient downloads it, have them verify rather than assume — how to view EXIF data walks through reading the fields back. A file that opens correctly is not proof, as our P3 and P4 rows show; if the bytes matter, compare hashes.

If you want the metadata gone: strip it locally before you attach. See how to erase EXIF data. Do not rely on the mail service to clean the file for you — a compliant attachment path is designed to deliver the bytes you gave it, which is exactly why it preserves EXIF in the first place.

If you are dealing with screenshots instead of camera photos: the starting point is different. Screenshots usually carry little or no camera EXIF at all, which is a separate question from whether a transport removed it. Our page on do screenshots have exif data covers what is typically in a screenshot to begin with.

If a photo arrived by email and you are trying to work out whether it is an original or a screenshot: the metadata test only helps once you know what the file should have contained. The do screenshots have exif data comparison is the useful reference here, and what EXIF data is explains the field groups (camera, exposure, GPS, orientation) you would be checking for. Orientation is a good canary: in our test the source carried Orientation = 6, and it survived every byte-identical path.

One last practical check. If you are sending a large original to preserve metadata, remember the documented 25 MB Gmail threshold from the official help page: past it, the file becomes a Drive link and this entire MIME analysis stops applying.

FAQ

Does email strip EXIF data from photo attachments? No, not on the path we tested. We built real MIME messages, sent a 201,441-byte JPEG through them and parsed it back: the attachment was byte-for-byte identical, with all 14 EXIF fields, the GPS block, XMP and IPTC intact. RFC 2045 §6.2 requires a transfer encoding to decode back to “the original sequence of octets which was encoded”. We did not test any real mail provider.

Does Gmail remove EXIF data from attached photos? We cannot say, because we did not send mail through Gmail. Gmail’s official attachment help page documents a 25 MB size limit and says oversized attachments are replaced with a Google Drive link; it does not contain the words EXIF, metadata, compression or original quality, and makes no statement about files being altered. We are not treating that silence as an answer either way.

Does inserting a photo into the message body preserve EXIF? At the MIME layer, yes in our test. We compared Content-Disposition: inline (with a Content-ID and an HTML part) against Content-Disposition: attachment. Both returned the identical 201,441-byte payload with identical metadata. RFC 2183 defines inline and attachment as presentation semantics, not data transformations. What a specific app does to the image before building the message is untested here.

Does base64 encoding change my image file? No. Base64 represents three input bytes as four ASCII characters; RFC 2045 §6.8 says the encoded data are “consistently only about 33 percent larger than the unencoded data”. In our measurement the 201,441-byte file became part of a 276,322-byte message, and the extracted attachment was still exactly 201,441 bytes with the same SHA-256. Base64 never decodes the JPEG.

Why did quoted-printable and 8bit change the bytes in your test? Because they are line-oriented encodings applied to binary data that contains bare CR and LF bytes. Our source JPEG had 1,092 bare LF and 518 bare CR bytes; both were normalised to CRLF, producing a 203,051-byte file and breaking the IPTC segment, though the JPEG still opened and EXIF still read 14 fields. RFC 2045 §6.7 explicitly warns that binary CR and LF must be encoded as =0D and =0A. This is a result from Python’s parser in our harness, not a claim about all mail software.

Does compressing or resizing a photo before attaching remove EXIF? In our control path, yes. We decoded the source JPEG and re-encoded it at quality 85 without explicitly carrying EXIF, then attached it with base64. The delivered file was 111,829 bytes with 0 EXIF fields and no GPS, XMP or IPTC. The email transport delivered that stripped file perfectly; the metadata was lost at the re-encoding step, before MIME was involved.

How can I check whether an attachment still has its EXIF? Read the fields back from the downloaded file with an EXIF viewer, and for a strict answer compare its hash with the original. A JPEG can open normally while its bytes have changed — our quoted-printable and 8bit paths still displayed 14 EXIF fields and GPS yet had lost their IPTC segment. See our guide on how to view EXIF data.

What happens to EXIF when an attachment exceeds Gmail's size limit? Gmail’s help page says that above 25 MB “Gmail automatically removes the attachment and adds it as a Google Drive link in the email”. At that point the image is not an email attachment, so the MIME analysis in this article does not apply. We did not test what Drive stores, and the help page makes no statement about metadata.

Related reading