I suspect I may not be describing the problem I have properly - perhaps this will help.
I know this is a long topic but I am totally new to TRichView and have spent a long time looking through the forums but the problem is that I probably would not know if I found the answer because I dont know if I have even the basic code right. I would truly appreciate any help that helps me to resolve this image issue as everything else seems to work well - even if I have coded it like a dummy
I am using RAD Studio 2009, Windows 7.
On our remote database server I have created a DBISAM 4 database that stores the following
"EMail Templates"
"EMail Recipient Groups"
"Email Recipients"
These tables are on the remote server because we have users in various offices and we always need to make sure they are using the right template and that these templates will be consistent.
Within the "EMail Templates" table we have the following fields
TEMPLATE_ID AUTOINC
TEMPLATE_NAME STRING
TEMPLATE_BODY BLOB
Our users use the TRichView editor (based on your Ribbon Demo) to create an Email Template. This template can include tables, lists and images in addition to the WYSIWYG edited text.
When the user completes editing a template they can save the template to the remote database "Email Templates" field. This is the code used to save the template.
procedure TfrmMain.DoSaveToTemplateDBExecute(Sender: TObject);
var
ms : TDBISAMBLOBStream;
begin
// make sure the remote DB is connected
if DBConnected then begin
try
// create the template save form and tidy up the input fields
with TfrmSaveTemplate.Create( nil ) do begin
ebName.Text := '';
ebDescription.Text := '';
ebCreatedBy.Text := '';
ebDateCreated.Text := DateToStr( Date );
btnLogin.Enabled := FALSE;
btnCancel.Enabled := TRUE;
// display the template save form modally and wait for response
ShowModal;
if ModalResult = mrOK then begin
// make sure the template does not exist
if not DT_TEMPLATES.FindKey( [ebName.Text] ) then begin
// add new record
DT_TEMPLATES.Append;
DT_TEMPLATES.FieldByName( 'NAME' ).AsString := ebName.Text;
DT_TEMPLATES.FieldByName( 'DESCRIPTION' ).AsString := ebDescription.Text;
DT_TEMPLATES.FieldByName( 'CREATED_BY' ).AsString := ebCreatedBy.Text;
DT_TEMPLATES.FieldByName( 'DATE_CREATED' ).AsDateTime := StrToDate( ebDateCreated.Text );
// create the stream - TDBISAMBLOBStream is fully compatible with streams - just easier to use with DBISAM
ms := TDBISAMBLOBStream.Create( TBlobField( DT_TEMPLATES.FieldByName( 'BODY' ) ), bmWrite );
// use SaveRVFToStream to save the template to the BLOB Field.
RichViewEdit1.SaveRVFToStream( ms, FALSE );
// free the stream - must do this before the Post
ms.Free;
// Post The Changes
DT_TEMPLATES.Post;
ShowMessage( 'Template Has Been Saved' );
end;
end;
end;
finally
frmSaveTemplate.Free;
end;
end;
end;
NOTE:
If the user has placed images in the editor they should be saved in the remote BLOB Field (written in the RVF to the BLOB field) but this does not seem to be happening so I have probebly missed something out of the above procedure. The images are instead written to the application folder which is not really what we need because these folders are going to get quite big.
When a user wants to send an email to a number of recipients the idea is to download an EMail Template from the remote server, make any changes and then just send the mail to the listed users...
Here is the loading code...
// load template from remote DB
procedure TfrmMain.actionLoadFromTemplateExecute(Sender: TObject);
var
fname : string;
begin
if DBConnected then begin
try
// create template load form (cbName combo box is filled with available template names)
with TfrmLoadTemplate.Create( nil ) do begin
btnLoad.Enabled := TRUE;
btnCancel.Enabled := TRUE;
ShowModal;
if ModalResult = mrOK then begin
if DT_TEMPLATES.FindKey( [cbName.Text] ) then begin
// we save to a file because saving to a stream and then opening the stream in TRichView didnt seem to work.
fname := format( '%s\%s.rvf', [FTemplateFolder,cbName.Text] );
TBlobField( DT_TEMPLATES.FieldByName( 'BODY' ) ).SaveToFile( fname );
RichViewEdit1.LoadRVF( fname );
RichViewedit1.Format;
// everything loaded fine but any images did not unless the image exists in the
// application folder - than the image displays OK
end;
end;
end;
finally
frmSaveTemplate.Free;
end;
end;
end;
Sending as EMail is as follows...
procedure TfrmMain.actionSendMailExecute(Sender: TObject);
var
MaxCount : Integer;
SendDelta : Integer;
SendCount : Integer;
PauseDelta : Integer;
begin
// No attachments allowed so we do not need to build attachments list
{
if not PrepareAttachments then begin
exit;
end;
}
// we do need the stringlist though to check later
Attachments := TStringList.Create;
{
btnSend.Enabled := False;
btnSend.Caption := 'Wait...';
}
DT_USERS.First;
SendCount := DT_USERS.RecordCount;
StatusBar1.Panels[1].Text := IntToStr( SendCount );
StatusBar1.Panels[3].Progress.Max := SendCount;
StatusBar1.Panels[3].Progress.Position := 0;
Application.ProcessMessages;
SendDelta := 0;
MaxCount := DT_MAILHOST.FieldByName( 'MAX_MAIL_COUNT' ).AsInteger;
DT_USERS.First;
while not DT_USERS.eof do begin
{ Basic Headers }
IdMessage1.Clear;
IdMessage1.From.Address := ebSenderMailAddress.Text;
IdMessage1.From.Name := ebMailFrom.Text;
{ check if the user has opted in }
if DT_USERS.FieldByName( 'USER_MAILOK' ).AsBoolean = TRUE then begin
with IdMessage1.Recipients.Add do begin
Address := DT_USERS.FieldByName( 'USER_EMAIL' ).AsString;
Name := DT_USERS.FieldByName( 'USER_NAME' ).AsString;
end;
IdMessage1.Subject := ebSubject.Text;
with IdMessage1.ReplyTo.Add do begin
Address := '
[email protected]';
Name := 'No Reply';
end;
HTMLImages := THTMLImagesCollection.Create;
try
BuildEmail;
finally
HTMLImages.Free;
end;
IdSMTP1.MailAgent := 'Brixx Bulk Mailer';
IdSMTP1.Host := ebMailHost.Text;
IdSMTP1.Port := StrToIntDef( ebMailPort.Text, 25);
IdSMTP1.Username := ebSenderMailAddress.Text;
IdSMTP1.Password := ebMailPassword.Text;
IdSMTP1.Connect;
try
IdSMTP1.Send(IdMessage1);
finally
IdSMTP1.Disconnect;
StatusBar1.Panels[3].Progress.Position := StatusBar1.Panels[3].Progress.Position + 1;
inc( SendDelta );
Application.ProcessMessages;
if SendDelta = MaxCount then begin
// insert delay here
end;
end;
end;
DT_USERS.Next;
end;
ShowMessage('Done');
end;
//
// Build the Email
// based on the demo code from TRichView forums
procedure TfrmMain.BuildEmail;
var
Stream : TMemoryStream;
ws : String;
s : TRVRawByteString;
i : Integer;
txtpart, htmpart, txthtmpart, txthtmlimgpart : TIdText;
imgpart : TIdAttachmentMemory;
begin
// saving text
TxtPart := TIdText.Create( IdMessage1.MessageParts );
Stream := TMemoryStream.Create;
RichViewEdit1.SaveTextToStreamW('', Stream, 80, False, False);
Stream.Position := 0;
SetLength(ws, Stream.Size div 2);
if Stream.Size <> 0 then begin
Stream.ReadBuffer(Pointer(ws)^, Stream.Size);
end;
Stream.Free;
txtpart.Body.Text := ws;
txtpart.ContentType := 'text/plain';
txtpart.ContentTransfer := 'quoted-printable';
txtpart.CharSet := 'utf-8';
// saving HTML
//
// QUESTION : Is there a way to insert the current recipient name in to the HTML message somewhere?
//
htmpart := TIdText.Create(IdMessage1.MessageParts);
Stream := TMemoryStream.Create;
RichViewEdit1.SaveHTMLToStreamEx(Stream, '', ebSubject.Text, '', '', '', '', [rvsoUseCheckpointsNames, rvsoUTF8]);
Stream.Position := 0;
SetLength(s, Stream.Size);
if Stream.Size<>0 then begin
Stream.ReadBuffer(Pointer(s)^, Stream.Size);
end;
Stream.Free;
htmpart.Body.Text := UTF8ToUnicodeString(s);
htmpart.ContentType := 'text/html';
htmpart.ContentTransfer := 'quoted-printable';
htmpart.CharSet := 'utf-8';
// combining text and HTML
IdMessage1.ContentType := 'multipart/alternative';
if (Attachments.Count=0) and (HTMLImages.Count=0) then begin
exit;
// should we actually exit here - not sure but we seem to be because no image is in the template.
end;
txthtmpart := TIdText.Create(IdMessage1.MessageParts);
txthtmpart.ContentType := 'multipart/alternative';
txthtmpart.Index := 0;
txtpart.ParentPart := txthtmpart.Index;
htmpart.ParentPart := txthtmpart.Index;
// images
for i := 0 to HTMLImages.Count-1 do begin
HTMLImages
.Stream.Position := 0;
imgpart := TIdAttachmentMemory.Create(IdMessage1.MessageParts, HTMLImages.Stream);
imgpart.ContentType := HTMLImages.ContentType;
imgpart.ContentID := '<'+HTMLImages.Name+'>';
imgpart.ContentDisposition := 'inline';
end;
// combining images and text+html
IdMessage1.ContentType := 'multipart/related; type="multipart/alternative"';
if Attachments.Count=0 then begin
//exit;
end;
if HTMLImages.Count>0 then begin
txthtmlimgpart := TIdText.Create(IdMessage1.MessageParts);
txthtmlimgpart.ContentType := 'multipart/related; type="multipart/alternative"';
txthtmlimgpart.Index := 0;
txthtmpart.ParentPart := txthtmlimgpart.Index;
for i := IdMessage1.MessageParts.Count-1-HTMLImages.Count to IdMessage1.MessageParts.Count-1 do begin
IdMessage1.MessageParts.ParentPart := txthtmlimgpart.Index;
end;
txtpart.ParentPart := txthtmpart.Index;
htmpart.ParentPart := txthtmpart.Index;
end;
// files - none required so skip this...
{
IdMessage1.ContentType := 'multipart/mixed';
for i := 0 to Attachments.Count-1 do begin
TIdAttachmentFile.Create(IdMessage1.MessageParts, Attachments);
end;
}
end;