Formatted emails (HTML email) from TAdvRichEditor

Bookmarks: 

Tuesday, September 12, 2017

Our TAdvRichEditor UI control has everything on-board to generate HTML from its rich document content, including exporting images that are possibly used in the document. Although generating this HTML can be easily done via the TAdvRichEditorHTMLIO non-visual component connected to the TAdvRichEditor, we frequently receive support emails from users struggling to use the generated HTML to send it as email with the Indy components (TIdMessage, TidSMPT).

Therefore, we decided not only to create a sample code snippet to show how this can be done, but also to create a non-visual component (available in the latest TMS Component Pack release) to reduce the code to generate such email message to the minimum possible, that is, to one line of code:
    emailio.GenerateEmail(idmessage);

But, back to full code first that shows how to use the Indy components to generate HTML emails with embedded images as this can be generally applied for cases also where no TAdvRichEditor is used.

Drop a TIdMessage component on the form. We create a multipart message, with a part for the plain text version of the email, a part for the HTML email header and a part for the HTML itself. Then we add attachments to the message where ContentDisposition is set to 'inline' and the ContentID is set to the ID used in the HTML image reference cid attribute. So, if we have in the HTML code an image reference like:

then the ContentID for the attachment containing the image will be :
ContentID := 'imageref1';

Now, let's put this together using a TAdvRichEditor, TAdvRichEditorHTMLIO, idMessage on the form. We set AdvRichEditorHTMLIO.RichEditor to the TAdvRichEditor instance we want to export. It is very important to set AdvRichEditor.HTMLImages to igID as this instructs the TAdvRichEditor to export images references as CID URI attributes. The export to HTML and image files from TAdvRichEditor becomes:
var
  i: integer;
begin
  AdvRichEditor1.HTMLImages := igID;
  // we save the output to a temporary HTML file
  AdvRichEditorHTMLIO1.Save('.
icheditor.html');

  for i := 0 to AdvRichEditor1.HTMLImageList.Count - 1 do
    begin
      // we prepare the images as temporary images files for use as attachments for the message
      AdvRichEditor1.HTMLImageList.Items[i].SaveToFile('.img'+i.ToString+'.png');
    end;
end;

As you can see, the images to be used in the export are available via the collection AdvRichEditor.HTMLImageList. From there, we can save the images to file to be used as attachments for the Indy idMessage. The code to construct the idMessage from here becomes:
  idMessage1.IsEncoded := True ;
  idMessage1.ContentType := 'multipart/alternative';
  idMessage1.ClearBody;

  with TIdText.Create(idMessage1.MessageParts, nil) do
  begin
    // here we include the text as plain text
    Body.Text := AdvRichEditor1.PlainText;
    ContentType := 'text/plain';
  end;

  with TIdText.Create(idMessage1.MessageParts, nil) do
  begin
    ContentType := 'multipart/related; type="text/html"';
  end;

  with TIdText.Create(idMessage1.MessageParts, nil) do
  begin
    // we load the content from the temporary HTML file
    Body.LoadFromFile('.
icheditor.html');
    ContentType := 'text/html';
    ParentPart := 1;
  end;

  // here we loop over images to add all as attachments 
  for i := 0 to FRichEditor.HTMLImageList.Count - 1 do
  begin
    with TIdAttachmentFile.Create(idMessage1.MessageParts,  + '.img' + i.ToString + '.png') do
    begin
      ContentID := 'image'+ i.ToString;
      ContentType := 'image/png';
      ContentDisposition := 'inline';
      ParentPart := 1;
    end;
  end;

When the idMessage message has been created, it is straightforward to send it via the idSMTP component, i.e., this is minimally:
  IdMessage1.From.Address := 'info@tmssoftware.com';
  IdMessage1.Recipients.Add.Address := 'bruno@tmssoftware.com';
  IdMessage1.Sender.Address := 'info@tmssoftware.com';

  idsmtp1.Host := 'smtp.mailserver.com';
  IdSMTP1.Connect;
  idsmtp1.Send(idMessage1);
  idsmtp1.Disconnect();

With this code now explained, let's introduce the class TAdvRichEditorEmailIO included in unit AdvRichEditorEMailIO.pas in the latest version 8.7.3.0 of TMS Component Pack. With this class, we can reduce the code to send a HTML email from TAdvRichEditor to:
  AdvRichEditorEMailIO.GenerateEmail(idmessage);
  idMessage.Subject := 'A HTML email from TAdvRichEditor';

  idSMTP1.Host := 'smtp.mailserver.com';
  IdSMTP1.Connect;
  idSMTP1.Send(idMessage);
  idSMTP1.Disconnect();

The resulting Delphi application looks like this:

and when opening the email sent in MS Outlook, it looks like:

You can easily get started to build your own HTML formatted text email client. You can download the source code of the application here and you can compile and use this with the latest TMS Component Pack release. In the next updates of TMS FMX UI Pack that also includes the FireMonkey version of our rich editor component, we'll also include a FireMonkey version of the HTML email creator class and the same applies for the cross-framework version of the rich editor in the TMS FNC UI Pack.

Bruno Fierens


Bookmarks: 

This blog post has received 5 comments.


1. Tuesday, September 12, 2017 at 8:40:25 PM

FYI, I have a blog article on the Indy website explaining how to create HTML emails with TIdMessage, including with embedded images:

http://www.indyproject.org/Sockets/Blogs/RLebeau/2005_08_17_A.asp

Also, Indy has a TIdMessageBuilderHtml class for populating a TIdMessage with content and attachments related to HTML emails:

http://www.indyproject.org/Sockets/Blogs/RLebeau/20080116.EN.aspx

Remy Lebeau


2. Tuesday, September 12, 2017 at 9:14:30 PM

As we''re loving your FNC cross-platform framework (which makes life SO MUCH EASIER supporting multiple OS with easy/appropriate choice of FMX, VCL or LCL as each project necessitates), it would be great to see your FNC concept extended to Web apps by embracing/supporting/integrating a "render as HTML/CSS/JavaScript (or TypeScript)" like IntraWeb and UniGUI do. Or am I just dreaming?

Ralston James


3. Tuesday, September 12, 2017 at 9:17:20 PM

Everything starts with a dream.

Bruno Fierens


4. Wednesday, September 13, 2017 at 2:52:53 PM

The Class TAdvRichEditorEmailIO is not registrated!
Is this correct? Must it created at Runtime?

Klaus Holtorf


5. Wednesday, September 13, 2017 at 3:00:35 PM

By design, we don''t want to add Indy dependency in our TMS Component Pack packages.

Bruno Fierens




Add a new comment:
Author:
Email:
  You will receive a confirmation mail with a link to validate your comment, so please use a valid email address.
Comment:
 
Change Image
Fill in the characters from the image above:
 

All fields are required.
 




Previous  |  Next  |  Index