trichview.com Forum Index trichview.com
TRichView support forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[Demo] Sending HTML email. Saving MIME-encoded files.
Goto page 1, 2  Next
 
Post new topic   Reply to topic    trichview.com Forum Index -> Examples, Demos
View previous topic :: View next topic  
Author Message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Sun Aug 28, 2005 11:27 am    Post subject: [Demo] Sending HTML email. Saving MIME-encoded files. Reply with quote

This example shows how to save HTML file with images in one file:

http://www.trichview.com/support/files/mime.zip

(It uses The Delphi Inspiration's DIMime unit for base64 encoding.
Its installation is included in the zip file above.
Their web page is http://www.yunqa.de/delphi/doku.php/products/mime/)

Update (2007-Sep-23): OnSaveImage2 is changed (see below), new demo for sending HTML e-mail using Indy.
Update (2008-Dec-11): updated version of DMime is included. Delphi\SaveFile demo can be used in all versions of Delphi, including 2009. Delphi\Indy is generally ok in D2009 too, but since TIdSMTP properties are changed, it should be corrected. C++Builder demo was not updated yet. On request.


Last edited by Sergey Tkachenko on Fri Jul 31, 2009 5:46 pm; edited 4 times in total
Back to top
View user's profile Send private message Visit poster's website
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Sun Oct 29, 2006 12:28 pm    Post subject: Reply with quote

This demo has wrong comment:
{ Actually, this demo converts all pictures to Jpegs, so only TJpegImage can
occur here. But you can use RV_RegisterHTMLGraphicFormat to allow other
graphic formats in HTML }

Actually, this demo saves all images in formats as they are. It uses OnSaveImage2 event, and images are passed to this event without conversion to jpegs. For the purposes of e-mail saving, you should convert images to jpegs (or png, or gifs). Change the code for this event to (and add CRVData in uses):
Code:
procedure TForm1.RichViewEdit1SaveImage2(Sender: TCustomRichView;
  Graphic: TGraphic; SaveFormat: TRVSaveFormat; const Path,
  ImagePrefix: String; var ImageSaveNo: Integer; var Location: String;
  var DoDefault: Boolean);
var gr: TGraphic;
    bmp: TBitmap;
begin
  if SaveFormat<>rvsfHTML then
    exit;
  if not (Graphic is TJPEGImage) and not RV_IsHTMLGraphicFormat(Graphic) then begin
    bmp := TBitmap.Create;
    try
      bmp.Assign(Graphic);
    except
      bmp.Width := Graphic.Width;
      bmp.Height := Graphic.Height;
      bmp.Canvas.Draw(0,0, Graphic);
    end;
    gr := TJPEGImage.Create;
    gr.Assign(bmp);
    bmp.Free;
    end
  else
    gr := Graphic;

  Location := Format('image%d.%s', [ImageSaveNo, GraphicExtension(TGraphicClass(gr.ClassType))]);
  inc(ImageSaveNo);
  with HTMLImages.Add as THTMLImageItem do
  begin
    gr.SaveToStream(Stream);
    Name := Location;
    ContentType := GetImageContentType(gr);
  end;
  Location := 'cid:'+Location;
  DoDefault := False;
  if gr<>Graphic then
    gr.Free;
end;
Back to top
View user's profile Send private message Visit poster's website
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Fri Nov 03, 2006 7:45 pm    Post subject: How to send this e-mail? Reply with quote

How to send TRichView document as formatted e-mail

This example uses TNMSMTP component

In the same demo, add the new function returning MIME-encoded document as string.
As you can see, there are 2 main differences comparing to the original file saving procedure from the demo:
1) headers are not included
2) not only HTML+images, but a plain text alternative is included.

Code:

uses RVUni;

function TForm1.GetEMail: String;
var Stream: TStringStream;
    Stream2: TMemoryStream;
    ws: WideString;
    s, s2: String;
    boundary: String;
    i: Integer;
begin

  // saving text
  HTMLImages.Clear;
  Stream2 := TMemoryStream.Create;
  RichViewEdit1.SaveTextToStreamW('', Stream2, 80, False, False);
  Stream2.Position := 0;
  SetLength(ws, Stream2.Size div 2);
  if Stream2.Size<>0 then
    Stream2.ReadBuffer(Pointer(ws)^, Stream2.Size);
  s2 := MimeEncodeString(Utf8Encode(ws));
  Stream2.Free;

  // saving HTML
  Stream := TStringStream.Create('');
  RichViewEdit1.SaveHTMLToStreamEx(Stream, '', 'Web Archive Demo', '', '', '', '',
    [rvsoUseCheckpointsNames, rvsoUTF8]);
  s := MimeEncodeString(Stream.DataString);
  Stream.Free;
  // now s contains HTML file without images, base64-encoded. saving it in MIME
  boundary := '----=_BOUNDARY_LINE_';

  Result :=
       'This is a multi-part message in MIME format.'+CRLF+CRLF+
       '--'+boundary+CRLF+
       'Content-Type: text/plain;'+CRLF+
       #9'charset="utf-8"'+CRLF+
       'Content-Transfer-Encoding: base64'+CRLF+CRLF+
       s2+CRLF+CRLF+
       '--'+boundary+CRLF+
       'Content-Type: text/html;'+CRLF+
       #9'charset="utf-8"'+CRLF+
       'Content-Transfer-Encoding: base64'+CRLF+CRLF+
       s+CRLF;

  // saving images
  for i := 0 to HTMLImages.Count-1 do begin
    s2 := CRLF+
          '--'+boundary+CRLF;
    SetLength(s, HTMLImages[i].Stream.Size);
    HTMLImages[i].Stream.Position := 0;
    HTMLImages[i].Stream.ReadBuffer(PChar(s)^, Length(s));
    s := MimeEncodeString(s);
    s2 := s2+'Content-Type: '+HTMLImages[i].ContentType+CRLF+
      #9'Name="'+HTMLImages[i].Name+'"'+CRLF+
      'Content-Transfer-Encoding: base64'+CRLF+
      'Content-ID: <'+HTMLImages[i].Name+'>'+CRLF+CRLF+
      s+CRLF;
    Result := Result+s2;
  end;
  Result := Result+CRLF+'--'+boundary+'--'+CRLF;
  HTMLImages.Clear;
end;


Sending:

Code:

    NMSMTP1.Host := ...;
    NMSMTP1.Port := ...;
    NMSMTP1.UserID := ...;
    NMSMTP1.Connect;

    NMSMTP1.PostMessage.FromAddress := ...;
    NMSMTP1.PostMessage.FromName := ...;
    NMSMTP1.PostMessage.ToAddress.Text := ...;
    NMSMTP1.PostMessage.ToCarbonCopy.Text := '';
    NMSMTP1.PostMessage.ToBlindCarbonCopy.Text := '';
    NMSMTP1.PostMessage.Body.Text := GetEMail;

    NMSMTP1.PostMessage.Attachments.Text := '';
    NMSMTP1.PostMessage.Subject := 'HTML Test';
    NMSMTP1.PostMessage.LocalProgram := 'Demo HTML Mailer';
    NMSMTP1.PostMessage.Date := '';
    NMSMTP1.PostMessage.ReplyTo := ...;
    NMSMTP1.SendMail;


The main trick is in adding headers in NMSMTP1.OnSendStart:

Code:
procedure TForm1.NMSMTP1SendStart(Sender: TObject);
begin
  NMSMTP1.FinalHeader.Add('MIME-Version: 1.0');
  NMSMTP1.FinalHeader.Add('Content-Type: multipart/alternative;');
  NMSMTP1.FinalHeader.Add(#9'boundary="----=_BOUNDARY_LINE_"');
end;


That's all.
Please do not abuse this feature.


Last edited by Sergey Tkachenko on Sat Nov 04, 2006 9:32 am; edited 3 times in total
Back to top
View user's profile Send private message Visit poster's website
alogrep



Joined: 27 Oct 2006
Posts: 38

PostPosted: Fri Nov 03, 2006 10:19 pm    Post subject: Reply with quote

Thanks Sergey
This looks a great neat feature.
1. what do you mean by "please do not abuse this feature"?
2. There is a little glitch: the mail body looks exactly as it should, however the 'Attachment' column in Outlook Express shows the symbol of the attachment, although there is no attachment: just the little clip.
I verified in SendStart, that PostMessaage.Attachments.Text=''.
Why does it show the little clip?
If i inspect SMTP1.PostMessage.Attachemtents i see (0, nil, nil, 0, 0, False, dupIgnore, nil, nil)
THANKS
Enrico
Back to top
View user's profile Send private message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Sat Nov 04, 2006 9:23 am    Post subject: Reply with quote

1. I asked to not use it for bad stuff
2. Strange, I cannot see the clip icon in my OE for such messages. Please send e-mail to me.
Back to top
View user's profile Send private message Visit poster's website
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Sat Nov 04, 2006 9:27 am    Post subject: How to send this e-mail? Reply with quote

How to send TRichView document as formatted e-mail - 2

This example uses Indy components: TIdSMTP and TIdMessage.

The function TForm1.GetEMail is the same as above.

Sending (assuming that SMTP server requires authorization):
Code:
    IdMessage1.Clear;

    IdMessage1.From.Address := ...;
    IdMessage1.From.Name := ...;

    with IdMessage1.Recipients.Add do begin
      Address := ...;
      Name := ...;
    end;

    with IdMessage1.ReplyTo.Add do begin
      Address := ...;
      Name := ...;
    end;

    IdMessage1.Body.Text := GetEMail;
    IdMessage1.Subject := 'HTML Test';

    IdMessage1.ExtraHeaders.Add('MIME-Version: 1.0');
    IdMessage1.ExtraHeaders.Add('Content-Type: multipart/alternative;');
    IdMessage1.ExtraHeaders.Add(#9'boundary="----=_BOUNDARY_LINE_"');

    IdSMTP1.MailAgent := 'Demo HTML Mailer';
    IdSMTP1.AuthenticationType := atLogin;
    IdSMTP1.Host := ...;
    IdSMTP1.Port := ...;
    IdSMTP1.UserId := ...;
    IdSMTP1.Password := ...;

    IdSMTP1.Connect;
    IdSMTP1.Send(IdMessage1);
Back to top
View user's profile Send private message Visit poster's website
alogrep



Joined: 27 Oct 2006
Posts: 38

PostPosted: Mon Nov 06, 2006 7:56 pm    Post subject: Reply with quote

Sent it using the program that uses your code. Did you receive it?
Back to top
View user's profile Send private message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Mon Nov 06, 2006 9:42 pm    Post subject: Reply with quote

Yes, and I cannot see the attachment icon. I use Outlook Express 6.00.2800.1123
Back to top
View user's profile Send private message Visit poster's website
alogrep



Joined: 27 Oct 2006
Posts: 38

PostPosted: Tue Nov 07, 2006 7:00 pm    Post subject: Reply with quote

Strange, I use the exact same OE. I did a lot of reserach on the web, none of the conditions described applies (OE could show the false Attachment icon, for example if there is a "begin " in the body of the message).
Anyway, I realize you cannot do much more. Thanks. One quetion: in this forum, it is only you that answers questions? Do the users share their tips and help with others?
Back to top
View user's profile Send private message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Tue Nov 07, 2006 9:14 pm    Post subject: Reply with quote

Answering questions here is a part of my work. Others may do it as a hobby Smile
In this forum ("Examples, Demos") only I can create a new topic.
Other users can post their examples, demos, help and tips in "Support" forum. If they are interesting for other users, I'll repost them here.
Back to top
View user's profile Send private message Visit poster's website
ohm0485



Joined: 09 Nov 2006
Posts: 2

PostPosted: Fri Nov 10, 2006 2:49 am    Post subject: access violation Reply with quote

I try to run your demo and occur access violation when call this method

RichViewEdit1.SaveHTMLToStreamEx(Stream, '', 'Web Archive Demo', '', '', '', '', [rvsoUseCheckpointsNames, rvsoUTF8]);


Thanks.
Back to top
View user's profile Send private message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Fri Nov 10, 2006 10:35 pm    Post subject: Reply with quote

What version of TRichView and Delphi?

Please compile the demo with stack frames and without optimization (Compiler tab in the project options).
Run the demo. Which line of TRichView (or the demo (probably the problem is in event)) code generates the error?
Back to top
View user's profile Send private message Visit poster's website
parkheaven



Joined: 20 Apr 2007
Posts: 1
Location: Lelystad The Netherlands

PostPosted: Fri Apr 20, 2007 3:12 am    Post subject: Mime encoded formatted e-mail Reply with quote

Dear Sergey,

The technique you use for sending mime encoded formatted e-mail
(see http://www.trichview.com/forums/viewtopic.php?t=11) works excellent! But how can I combine this technique with sending a 'normal' attachment?

TIdAttachment.Create(IdMessage.MessageParts, s) does not work together with the ExtraHeaders addition.

We are integrating an email client into a CRM program and experimenting with the TRichView trial version. If we can use this technique and send real attachments too, we are definitely in!

Hope you or anyone else can help...
Back to top
View user's profile Send private message
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Fri Apr 20, 2007 4:34 pm    Post subject: Reply with quote

You cannot use Indy's MIME features. Indy must think that this is a plain text e-mail.
Ok, let's assume that we have Attachments: TStringList with paths to attached files.

Modify GetEmail function (see above).
Add Stream3: TFileStream to vars.
Add the code below to the end of this function
(before
Code:
  Result := Result+CRLF+'--'+boundary+'--'+CRLF;
  HTMLImages.Clear;
end;
)
Code to add:
Code:
// saving attached files
  for i := 0 to Attachments.Count-1 do begin
    s := ExtractFileName(Attachments[i]);
    s2 := CRLF+ '--'+boundary+CRLF+
   'Content-Type: application/octet-stream; name="'+s+'"'+CRLF+
   'Content-Disposition: attachment; filename="'+s+'"+CRLF+
   'Content-Transfer-Encoding: base64+CRLF+CRLF;
   Stream3 := TFileStream.Create(Attachments[i], fmOpenRead);
   try
     SetLength(s, Stream3.Size);
     Stream3.ReadBuffer(PChar(s)^, Stream3.Size);
   except
     s := '(Cannot load file)';
   end;
   Stream3.Free;
   s := MimeEncodeString(s);
   Result := Result + s2+s+CRLF;
end;


PS: I wrote this code in browser, not tested.
Possible problems with this code: if file names have non-English characters, they must be encoded somehow
Back to top
View user's profile Send private message Visit poster's website
Sergey Tkachenko
Site Admin


Joined: 27 Aug 2005
Posts: 6576

PostPosted: Sun Sep 23, 2007 5:23 pm    Post subject: Reply with quote

Update: http://www.trichview.com/support/files/mime.zip contains demo for sending HTML e-mail with Indy.

Updated 2008-Jan-4:
E-mail structure used with the SendEmail project is changed. E-mails sent by the previous version were read by Outlook Express, but other mailers had problems. Now documents generated by GetEMail have a nested structure: (((text, HTML), image, image, ...), file, file, ...). Only SendEmail demo was changed (for file saving, text and attachments are not supported, so nested structure was not required).
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    trichview.com Forum Index -> Examples, Demos All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group