How to process MIME format with inline image separated into a different boundary using TIdMessage?

54 Views Asked by At

I have a MIME format as below:

Content-Type: multipart/alternative; boundary="qawqKLHOZYgscUPhZKw5hacv=_UlERjiEj"
MIME-Version: 1.0
Date: Mon, 25 Mar 2024 10:17:34 +0800

This is a multi-part message in MIME format

--qawqKLHOZYgscUPhZKw5hacv=_UlERjiEj
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Sample HTML

--qawqKLHOZYgscUPhZKw5hacv=_UlERjiEj
Content-Type: multipart/related; type="text/html";
    boundary="5SZQJxkhHuQyExC8cj=_sPNysz4gQuoIGj"

--5SZQJxkhHuQyExC8cj=_sPNysz4gQuoIGj
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

<P><STRONG>Sample HTML</STRONG></P>
<P><STRONG><IMG style=3D"HEIGHT: 184px; WIDTH: 194px" border=3D0 hspac=
e=3D0 alt=3D"" src=3D"cid:/Desktop/potato.gif" width=3D495 align=3Dbas=
eline height=3D497></STRONG></P>

--5SZQJxkhHuQyExC8cj=_sPNysz4gQuoIGj
Content-Type: image/gif;
    name="/Desktop/potato.gif"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
    filename="/Desktop/potato.gif"
Content-ID: </Desktop/potato.gif>

<base 64 data>

--5SZQJxkhHuQyExC8cj=_sPNysz4gQuoIGj--

--qawqKLHOZYgscUPhZKw5hacv=_UlERjiEj--

.

How can I render back the HTML by plugging in the Base64 back into the HTML? The library that I'm using is TIdMessage. For prototyping purposes, I currently load my MIME from a text file. So far I'm only able to check Content-Disposition and Content-Type, but I'm not sure how to access the content. For the HTML, I'm able to access it using TIdText.Body, but there's no body option when using TIdAttachment:

var vMsg := TIdMessage.Create(nil);
try
  vMsg.LoadFromFile('D:\Desktop\Complete MIME 2.txt');
  for var i := 0 to vMsg.MessageParts.Count - 1 do begin
    var o := vMsg.MessageParts.Items[i];

    if (o.PartType = TIdMessagePartType.mptAttachment) then begin
      if o.ContentDisposition.Equals('inline') then begin
        var sContentID := o.ContentID.Substring(1, o.ContentID.Length - 2);

        // how to retrieve inline image base 64?
      end;
    end;
  end;
finally
  vMsg.Free;
end;

Update: I have tried access the TIdAttachment using the OpenLoadStream as Remy suggested and printed the result but I only got ÿØÿà. Code as below:

var vAttachment := TIdAttachment(o);
var vAttachmentStream := vAttachment.OpenLoadStream;
var vStringStream := TStringStream.Create;
try
  vStringStream.LoadFromStream(vAttachmentStream);
  vStringStream.Position := 0;
  OutputDebugString(PChar(vStringStream.DataString));
finally
  vAttachment.CloseLoadStream;
  vStringStream.Free;
end;
1

There are 1 best solutions below

2
Remy Lebeau On

How can I render back the HTML by plugging in the Base64 back into the HTML?

Such HTML expects the image to be loaded directly from the MIME data using a cid: that refers to the specific MIME attachment. To render this HTML properly, you need a renderer that understands MIME, or at least provides a way for you to give it the image data for a given cid. Otherwise, you will have to save the attachment data to a file and then update the HTML to refer to that file before rendering it.

So far I'm only able to check Content-Disposition and Content-Type, but I'm not sure how to access the content. For the HTML, I'm able to access it using TIdText.Body, but there's no body option when using TIdAttachment

TIdAttachment has an OpenLoadStream() method for accessing its data. The base64 will have already been decoded for you before the TIdAttachment is created, so you will get a TStream to the actual image data. Call CloseLoadStream() when you are done using the TStream.