[Demo] Sending HTML email. Saving MIME-encoded files.
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
[Demo] Sending HTML email. Saving MIME-encoded files.
This example shows how to save HTML file with images in one file:
https://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/
Note (2012-May-9): the new demo in Delphi\Indy does not use this unit)
https://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/
Note (2012-May-9): the new demo in Delphi\Indy does not use this unit)
Last edited by Sergey Tkachenko on Wed May 09, 2012 10:17 am, edited 8 times in total.
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
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):
{ 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: Select all
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;
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
How to send this e-mail?
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.
Sending:
The main trick is in adding headers in NMSMTP1.OnSendStart:
That's all.
Please do not abuse this feature.
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: Select all
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;
Code: Select all
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;
Code: Select all
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;
Please do not abuse this feature.
Last edited by Sergey Tkachenko on Sat Nov 04, 2006 9:32 am, edited 3 times in total.
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
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
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
How to send this e-mail?
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):
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: Select all
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);
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
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?
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?
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
access violation
I try to run your demo and occur access violation when call this method
RichViewEdit1.SaveHTMLToStreamEx(Stream, '', 'Web Archive Demo', '', '', '', '', [rvsoUseCheckpointsNames, rvsoUTF8]);
Thanks.
RichViewEdit1.SaveHTMLToStreamEx(Stream, '', 'Web Archive Demo', '', '', '', '', [rvsoUseCheckpointsNames, rvsoUTF8]);
Thanks.
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
-
- Posts: 1
- Joined: Fri Apr 20, 2007 2:51 am
- Location: Lelystad The Netherlands
Mime encoded formatted e-mail
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...
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...
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
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 to add:
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
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: Select all
Result := Result+CRLF+'--'+boundary+'--'+CRLF;
HTMLImages.Clear;
end;
Code to add:
Code: Select all
// 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;
Possible problems with this code: if file names have non-English characters, they must be encoded somehow
-
- Site Admin
- Posts: 16238
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
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).
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).