mierlp Posted January 1, 2013 Posted January 1, 2013 Hi, I was wondering how you send e-mail. I know Indy can be used, but i find in not the best solution for my Win32 applications so i switched to AddEmail from Traysoft. A nice feature is that you can import a html file into the body of the message. Using FastReport the user could create a report for his e-mail body. The report was exported to html and then imported into the e-mail message body. AddEmail is a active X and you have several non visual components which can be used with uniGui Questions: - how do you facilitate composing/sending a single mail to a user...do you have a self build mail form? normally i used the shellexecute for calling the default mail client...in web mode that's not what you want - how do facilitate composing/sending bulk mail to all clients within you database? Tips...suggestions..ideas, samples are welcome Regards Peter Quote
Oliver Morsch Posted January 1, 2013 Posted January 1, 2013 I use indy (idSmtp, idPop3, idMessage) for sending and receiving mails. For viewing i use uniHtmlFrame and uniHtmlMemo as (HTML-)editor. All mails are stored in a firebird database. Quote
Ronak Posted January 2, 2013 Posted January 2, 2013 Hi,Compose the mail and store to database, once the mail is ready to be send, call the mail sender, see the code unit MailsForm; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uniGUITypes, uniGUIAbstractClasses, uniGUIClasses, uniGUIForm, StrUtils, IdCoderMIME, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase, IdMessageClient, IdSMTPBase, IdSMTP, IdMessage, IdAttachment, IdAttachmentFile, IdText, DB, ADODB, uniGUIBaseClasses, uniButton; type TFormMails = class(TUniForm) QryMain: TADOQuery; QryMainEmailId: TAutoIncField; QryMainFolder: TIntegerField; QryMainTagIO: TStringField; QryMainRefDate: TDateTimeField; QryMainSize: TIntegerField; QryMainFromEmail: TMemoField; QryMainToEmail: TMemoField; QryMainCCEmail: TMemoField; QryMainBCCEmail: TMemoField; QryMainSubject: TMemoField; QryMainBody: TMemoField; QryMainRawMsg: TBlobField; QryMainIsSubmitted: TBooleanField; QryMainIsSent: TBooleanField; QryMainSentDate: TDateTimeField; QryMainUsersId: TIntegerField; QryMainIsReaded: TBooleanField; QryMainMainId: TAutoIncField; QryMainTndrId: TIntegerField; QryDetailA: TADOQuery; QryDetailAEmailDetId: TAutoIncField; QryDetailAEmailId: TIntegerField; QryDetailAAtchFileName: TStringField; QryDetailAAtchFileData: TBlobField; QryDetailAAtchSize: TIntegerField; QryDetailAMainId: TIntegerField; ButtonSendMail: TUniButton; procedure ButtonSendMailClick(Sender: TObject); private procedure SendHtmlMail; procedure ProcessHtml(var HBody: WideString; AtchList: TStringList); procedure Decode2File(const base64: String; const FileName: string); function MyBase64Decode(const EncodedText: string): TBytes; { Private declarations } public { Public declarations } end; implementation uses uniGUIApplication, ServerModule, MainModule; {$R *.dfm} { TUniForm1 } procedure TFormMails.ButtonSendMailClick(Sender: TObject); begin if not (QryMain.State in [dsInsert,dsEdit]) then QryMain.Edit; QryMainIsSubmitted.Value:=True; QryMain.Post; if (not QryMainIsSent.AsBoolean) and (QryMainIsSubmitted.AsBoolean) then SendHtmlMail(); end; procedure TFormMails.Decode2File(const base64, FileName: string); var stream: TFileStream; bytes: TBytes; begin bytes := MyBase64Decode(base64); stream := TFileStream.Create(FileName, fmCreate); try if bytes<>nil then stream.Write(bytes[0], Length(Bytes)); finally stream.Free; end; end; function TFormMails.MyBase64Decode(const EncodedText: string): TBytes; var DecodedStm: TBytesStream; Decoder: TIdDecoderMIME; begin Decoder := TIdDecoderMIME.Create(nil); try DecodedStm := TBytesStream.Create; try Decoder.DecodeBegin(DecodedStm); Decoder.Decode(EncodedText); Decoder.DecodeEnd; Result := DecodedStm.Bytes; SetLength(Result, DecodedStm.Size); finally DecodedStm.Free; end; finally Decoder.Free; end; end; procedure TFormMails.ProcessHtml(var HBody: WideString; AtchList: TStringList); var sHtm,sBase: WideString; i,iCid,iPart,klen: integer; sKey,TmpAtchfile: String; bSkip:Boolean; begin AtchList.Clear; sHtm := QryMainBody.AsString; sKey := '<img src="data:'; klen := length(sKey); bSkip:= False; iCid := 0; HBody:= ''; sBase:= ''; iPart:= 1; for i:=1 to Length(sHtm) do begin if iPart=1 then HBody:=HBody +sHtm[i] else if iPart=2 then begin if not bSkip then sBase:=sBase +sHtm[i]; if (RightStr(sBase,7)= 'base64,') then sBase:=''; if (RightStr(sBase,6)= '" alt=') then begin SetLength(sBase,length(sBase)-6); bSkip:=True; end; end; if (iPart=1) and (RightStr(HBody, klen)=sKey) then iPart:=2 else if (iPart=2) and (sHtm[i]='>') then begin iPart:=1; bSkip:=False; SetLength(HBody, length(HBody)-5); HBody := HBody +'cid:ImgID' +InttoStr(iCid) +'">'; TmpAtchfile := UniServerModule.LocalCachePath +'Tmp'+InttoStr(iCid); Decode2File(sBase, pchar(TmpAtchfile)); sBase:=''; AtchList.Add(TmpAtchfile); iCid:=iCid+1; end; end; end; procedure TFormMails.SendHtmlMail; var i:Integer; HtmPart, TxtPart: TIdText; BmpPart: TIdAttachment; Msg: TIdMessage; IdSMTP: TIdSMTP; AtchFile, sSql: String; sHBody: WideString; AtchList: TStringList; begin sHBody:=''; AtchList:= TStringList.Create; ProcessHtml(sHBody, AtchList); Msg := TIdMessage.Create(nil); Msg.From.address := QryMainFromEmail.AsString; Msg.Recipients.EMailAddresses := QryMainToEmail.AsString; Msg.CCList.EMailAddresses := QryMainCCEmail.AsString; Msg.BccList.EMailAddresses := QryMainBCCEmail.AsString; Msg.Subject := QryMainSubject.AsString; Msg.ContentType := 'multipart/alternative'; TxtPart := TIdText.Create(Msg.MessageParts); TxtPart.ContentType := 'text/plain'; TxtPart := TIdText.Create(Msg.MessageParts); TxtPart.ContentType := 'multipart/related; type="text/html"'; HtmPart := TIdText.Create(Msg.MessageParts, nil); HtmPart.ContentType := 'text/html'; HtmPart.Body.Add('<html>'); HtmPart.Body.Add('<head>'); HtmPart.Body.Add('</head>'); HtmPart.Body.Add('<body>'); HtmPart.Body.Add(sHBody); HtmPart.Body.Add('</body>'); HtmPart.Body.Add('</html>'); HtmPart.ParentPart := 1; for i:=0 to AtchList.Count-1 do begin BmpPart := TIdAttachmentFile.Create(Msg.MessageParts, pchar(AtchList[i])); BmpPart.ContentType := 'image/jpeg'; BmpPart.ContentDisposition := 'inline'; BmpPart.ContentID := 'ImgID'+ IntToStr(i); BmpPart.ParentPart := 1; end; Msg.ContentType := 'multipart/mixed'; QryDetailA.First; while not QryDetailA.Eof do begin AtchFile := UniServerModule.LocalCachePath +QryDetailAAtchFileName.AsString; QryDetailAAtchFileData.SaveToFile(PChar(AtchFile)); TIdAttachmentFile.Create(Msg.MessageParts, AtchFile); QryDetailA.Next; end; IdSMTP := TIdSMTP.Create(nil); with UniMainModule do begin idSMTP.Username := QryFirmSmtpUser.AsString; idSMTP.Password := QryFirmSmtpPw.AsString; idSMTP.Host := QryFirmSmtpHost.AsString; idSMTP.Port := QryFirmSmtpPort.AsInteger; end; try idSMTP.Connect(); try idSMTP.Send(Msg); sSql:= 'UPDATE Email SET Folder = 1, IsSent = 1, SentDate = GETDATE() WHERE (EmailId=0'; sSql:= sSql +QryMainMainId.AsString +')'; UniMainModule.Conn.Execute(Pchar(sSql)); ShowMessage('Message Sent'); except on E: Exception do ShowMessage('Failed: ' + E.Message); end; finally if IdSMTP.Connected then idSMTP.Disconnect(); Msg.Free; IdSMTP.Free; AtchList.Clear; AtchList.Free; end; end; end. TestEMails.rar TestRetriveMails.rar Quote
mierlp Posted January 2, 2013 Author Posted January 2, 2013 Hi, Nice code Ronak...i'm going to test it. @Oliver : did you build some kind of 'outlook' look-and-feel for the user for sending/reading e-mail ? Regards Peter Quote
Oliver Morsch Posted January 2, 2013 Posted January 2, 2013 @Oliver : did you build some kind of 'outlook' look-and-feel for the user for sending/reading e-mail ? My current test version looks like this: Quote
mierlp Posted January 2, 2013 Author Posted January 2, 2013 Hi Oliver, Thanks for sharing...looks very nice/good. How do you send bulk mail and do you use some kind of mail merge...integrate some personal values from a database ? Regards Peter My current test version looks like this: Quote
Oliver Morsch Posted January 2, 2013 Posted January 2, 2013 How do you send bulk mail and do you use some kind of mail merge...integrate some personal values from a database ? Not at present, but it is planned for the future. I think i will simply have a text like "dear [NAME], ..." and then replace [NAME] and more by a sql query... I don't know at this time if we will need master/detail-relations (e.g. invoice items) in the email or sending such things as PDF-Attachment. But i have developped such a behavior (master/detail with text replacing) a few years ago for a RTF-Report. It works, but is too difficult for most users, so we must deliver the "reports" (sql-relations, ...). Quote
mierlp Posted January 3, 2013 Author Posted January 3, 2013 Hi Oliver, Within our Windows applications we only used 'standard' mail messages. Those 'messages/layout' are created in FastReport as a report, so the user can access all database and fields he needs. When they send a message the report was automaticly exported to a mail.html file which was imported into te mail body. In this case the user can make his 'message' he wants, including images, text, colors etc. Works fine...but not in uniGui mode...that's also the reason about my other thread 'How facilitate reporting'. I have also used 'search/replace' but it's to difficult for users. Regards Peter Not at present, but it is planned for the future. I think i will simply have a text like "dear [NAME], ..." and then replace [NAME] and more by a sql query... I don't know at this time if we will need master/detail-relations (e.g. invoice items) in the email or sending such things as PDF-Attachment. But i have developped such a behavior (master/detail with text replacing) a few years ago for a RTF-Report. It works, but is too difficult for most users, so we must deliver the "reports" (sql-relations, ...). Quote
Oliver Morsch Posted January 3, 2013 Posted January 3, 2013 I have also used 'search/replace' but it's to difficult for users. Do you (your users) need 1:n-relations in the message body? Or is 1 query (record) -> 1 mail(body) enough? Quote
mierlp Posted January 3, 2013 Author Posted January 3, 2013 Hi Oliver In this case they only need 1 query (record) -> 1 mail(body) because we only need some fields out of the CONTACT database like : LastName, FirstName, MiddeName Regards Peter Quote
Oliver Morsch Posted January 3, 2013 Posted January 3, 2013 In this case they only need 1 query (record) -> 1 mail(body) because we only need some fields out of the CONTACT database like : LastName, FirstName, MiddeName In this case it should be simple to give the user a TUniHmlMemo (or "tiny MCE" component) for editing the mail. The user must only insert things like [LastName] or you give him buttons to insert this. And then you must replace all [Fieldnames] with the value of the current record before sending. Where do you have problems? Quote
mierlp Posted January 4, 2013 Author Posted January 4, 2013 Hi Oliver, The problem then was the replacement from the [LastName] into real fieldnames so it can be used with a query. Because the code was unuseless we did'nt used/saved it and found other solutions. I now build my 'simple' mail form (based on you're suggestion) so the user can send a e-mail. For sending mail is prefer using stable components. I've tested the following components, which are all working in Win32 but have some problems when using them in uniGui: - Mailbee Smtp ActiveX (http://www.afterlogic.com/mailbee/objects but have a problem (Componentent not connected tot a services) when i want the send the message the second time. I used it in Win32 apps and it's a older version maybe a upgrade must be done and i will mail them about the error - AddEmail ActiveX(http://www.traysoft.com/addemail_overview.htm The problem here is a got a AccessViolation when a set the serialnumber for the component...even when i do it in uniGui VCL mode...in a normal Win32 applications it's working. I've send them a mail for support. Both components support a way of bullk mail...so if you have to send 500 mails to you're customers Regards Peter Quote
Oliver Morsch Posted January 5, 2013 Posted January 5, 2013 I now build my 'simple' mail form (based on you're suggestion) so the user can send a e-mail. For sending mail is prefer using stable components. I've tested the following components, which are all working in Win32 but have some problems when using them in uniGui: - Mailbee Smtp ActiveX (http://www.afterlogic.com/mailbee/objects but have a problem (Componentent not connected tot a services) when i want the send the message the second time. I used it in Win32 apps and it's a older version maybe a upgrade must be done and i will mail them about the error - AddEmail ActiveX(http://www.traysoft.com/addemail_overview.htm The problem here is a got a AccessViolation when a set the serialnumber for the component...even when i do it in uniGui VCL mode...in a normal Win32 applications it's working. I've send them a mail for support. Have you tried to set "autocoinicialize" to true? (Autocoinitialize) Quote
mierlp Posted January 5, 2013 Author Posted January 5, 2013 Yep...did set it to TRUE, but didn't solved the problem. There another strange behavior of the AddEmail Active X. After i put the component on the form, save the project, reopen the project the component is not visible any more and when compeling i got the message : Field FormMailBasic.SmtpMail does not have a corresponding component. Remove the declaration Yes/No/Cancel I think it's because the component has a big size icon wereby it's 'visual' Regards Peter Have you tried to set "autocoinicialize" to true? (Autocoinitialize) Quote
Ronak Posted January 7, 2013 Posted January 7, 2013 Hello, Try, Creating the AddEmail Active-X object at run time and the set the required property values instead of dropping the component on the form at design time. Regards 1 Quote
mierlp Posted January 7, 2013 Author Posted January 7, 2013 Hi Ronak, Thanks for the tip...it was took some puzzle time, but i got it working that way...great/thanks Regards Peter Hello, Try, Creating the AddEmail Active-X object at run time and the set the required property values instead of dropping the component on the form at design time. Regards Quote
mhmda Posted April 29, 2013 Posted April 29, 2013 Thanx for this, Can I send image inside the body (not attached)? Quote
Ronak Posted April 30, 2013 Posted April 30, 2013 Thanx for this, Can I send image inside the body (not attached)? Yes, we can send image inside the body, it works, May Open the mail with OE. Quote
mehmet07 Posted May 13, 2013 Posted May 13, 2013 Hi, Yes, we can send image inside the body, it works, May Open the mail with OE. what is OE? Quote
mdagli2001@gmail.com Posted February 12, 2019 Posted February 12, 2019 On 1/2/2013 at 7:25 AM, Ronak said: Hi, Compose the mail and store to database, once the mail is ready to be send, call the mail sender, see the code unit MailsForm; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uniGUITypes, uniGUIAbstractClasses, uniGUIClasses, uniGUIForm, StrUtils, IdCoderMIME, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase, IdMessageClient, IdSMTPBase, IdSMTP, IdMessage, IdAttachment, IdAttachmentFile, IdText, DB, ADODB, uniGUIBaseClasses, uniButton; type TFormMails = class(TUniForm) QryMain: TADOQuery; QryMainEmailId: TAutoIncField; QryMainFolder: TIntegerField; QryMainTagIO: TStringField; QryMainRefDate: TDateTimeField; QryMainSize: TIntegerField; QryMainFromEmail: TMemoField; QryMainToEmail: TMemoField; QryMainCCEmail: TMemoField; QryMainBCCEmail: TMemoField; QryMainSubject: TMemoField; QryMainBody: TMemoField; QryMainRawMsg: TBlobField; QryMainIsSubmitted: TBooleanField; QryMainIsSent: TBooleanField; QryMainSentDate: TDateTimeField; QryMainUsersId: TIntegerField; QryMainIsReaded: TBooleanField; QryMainMainId: TAutoIncField; QryMainTndrId: TIntegerField; QryDetailA: TADOQuery; QryDetailAEmailDetId: TAutoIncField; QryDetailAEmailId: TIntegerField; QryDetailAAtchFileName: TStringField; QryDetailAAtchFileData: TBlobField; QryDetailAAtchSize: TIntegerField; QryDetailAMainId: TIntegerField; ButtonSendMail: TUniButton; procedure ButtonSendMailClick(Sender: TObject); private procedure SendHtmlMail; procedure ProcessHtml(var HBody: WideString; AtchList: TStringList); procedure Decode2File(const base64: String; const FileName: string); function MyBase64Decode(const EncodedText: string): TBytes; { Private declarations } public { Public declarations } end; implementation uses uniGUIApplication, ServerModule, MainModule; {$R *.dfm} { TUniForm1 } procedure TFormMails.ButtonSendMailClick(Sender: TObject); begin if not (QryMain.State in [dsInsert,dsEdit]) then QryMain.Edit; QryMainIsSubmitted.Value:=True; QryMain.Post; if (not QryMainIsSent.AsBoolean) and (QryMainIsSubmitted.AsBoolean) then SendHtmlMail(); end; procedure TFormMails.Decode2File(const base64, FileName: string); var stream: TFileStream; bytes: TBytes; begin bytes := MyBase64Decode(base64); stream := TFileStream.Create(FileName, fmCreate); try if bytes<>nil then stream.Write(bytes[0], Length(Bytes)); finally stream.Free; end; end; function TFormMails.MyBase64Decode(const EncodedText: string): TBytes; var DecodedStm: TBytesStream; Decoder: TIdDecoderMIME; begin Decoder := TIdDecoderMIME.Create(nil); try DecodedStm := TBytesStream.Create; try Decoder.DecodeBegin(DecodedStm); Decoder.Decode(EncodedText); Decoder.DecodeEnd; Result := DecodedStm.Bytes; SetLength(Result, DecodedStm.Size); finally DecodedStm.Free; end; finally Decoder.Free; end; end; procedure TFormMails.ProcessHtml(var HBody: WideString; AtchList: TStringList); var sHtm,sBase: WideString; i,iCid,iPart,klen: integer; sKey,TmpAtchfile: String; bSkip:Boolean; begin AtchList.Clear; sHtm := QryMainBody.AsString; sKey := '<img src="data:'; klen := length(sKey); bSkip:= False; iCid := 0; HBody:= ''; sBase:= ''; iPart:= 1; for i:=1 to Length(sHtm) do begin if iPart=1 then HBody:=HBody +sHtm[i] else if iPart=2 then begin if not bSkip then sBase:=sBase +sHtm[i]; if (RightStr(sBase,7)= 'base64,') then sBase:=''; if (RightStr(sBase,6)= '" alt=') then begin SetLength(sBase,length(sBase)-6); bSkip:=True; end; end; if (iPart=1) and (RightStr(HBody, klen)=sKey) then iPart:=2 else if (iPart=2) and (sHtm[i]='>') then begin iPart:=1; bSkip:=False; SetLength(HBody, length(HBody)-5); HBody := HBody +'cid:ImgID' +InttoStr(iCid) +'">'; TmpAtchfile := UniServerModule.LocalCachePath +'Tmp'+InttoStr(iCid); Decode2File(sBase, pchar(TmpAtchfile)); sBase:=''; AtchList.Add(TmpAtchfile); iCid:=iCid+1; end; end; end; procedure TFormMails.SendHtmlMail; var i:Integer; HtmPart, TxtPart: TIdText; BmpPart: TIdAttachment; Msg: TIdMessage; IdSMTP: TIdSMTP; AtchFile, sSql: String; sHBody: WideString; AtchList: TStringList; begin sHBody:=''; AtchList:= TStringList.Create; ProcessHtml(sHBody, AtchList); Msg := TIdMessage.Create(nil); Msg.From.address := QryMainFromEmail.AsString; Msg.Recipients.EMailAddresses := QryMainToEmail.AsString; Msg.CCList.EMailAddresses := QryMainCCEmail.AsString; Msg.BccList.EMailAddresses := QryMainBCCEmail.AsString; Msg.Subject := QryMainSubject.AsString; Msg.ContentType := 'multipart/alternative'; TxtPart := TIdText.Create(Msg.MessageParts); TxtPart.ContentType := 'text/plain'; TxtPart := TIdText.Create(Msg.MessageParts); TxtPart.ContentType := 'multipart/related; type="text/html"'; HtmPart := TIdText.Create(Msg.MessageParts, nil); HtmPart.ContentType := 'text/html'; HtmPart.Body.Add('<html>'); HtmPart.Body.Add('<head>'); HtmPart.Body.Add('</head>'); HtmPart.Body.Add('<body>'); HtmPart.Body.Add(sHBody); HtmPart.Body.Add('</body>'); HtmPart.Body.Add('</html>'); HtmPart.ParentPart := 1; for i:=0 to AtchList.Count-1 do begin BmpPart := TIdAttachmentFile.Create(Msg.MessageParts, pchar(AtchList[i])); BmpPart.ContentType := 'image/jpeg'; BmpPart.ContentDisposition := 'inline'; BmpPart.ContentID := 'ImgID'+ IntToStr(i); BmpPart.ParentPart := 1; end; Msg.ContentType := 'multipart/mixed'; QryDetailA.First; while not QryDetailA.Eof do begin AtchFile := UniServerModule.LocalCachePath +QryDetailAAtchFileName.AsString; QryDetailAAtchFileData.SaveToFile(PChar(AtchFile)); TIdAttachmentFile.Create(Msg.MessageParts, AtchFile); QryDetailA.Next; end; IdSMTP := TIdSMTP.Create(nil); with UniMainModule do begin idSMTP.Username := QryFirmSmtpUser.AsString; idSMTP.Password := QryFirmSmtpPw.AsString; idSMTP.Host := QryFirmSmtpHost.AsString; idSMTP.Port := QryFirmSmtpPort.AsInteger; end; try idSMTP.Connect(); try idSMTP.Send(Msg); sSql:= 'UPDATE Email SET Folder = 1, IsSent = 1, SentDate = GETDATE() WHERE (EmailId=0'; sSql:= sSql +QryMainMainId.AsString +')'; UniMainModule.Conn.Execute(Pchar(sSql)); ShowMessage('Message Sent'); except on E: Exception do ShowMessage('Failed: ' + E.Message); end; finally if IdSMTP.Connected then idSMTP.Disconnect(); Msg.Free; IdSMTP.Free; AtchList.Clear; AtchList.Free; end; end; end. TestEMails.rar TestRetriveMails.rar merhabalar, süper bir kod örneği, bir kısmını çalıştırdım, dosya ekleyip gönderiyorum ancak mail gövdesine metin ekleyemedim. html sayfayı ekleyemiyorum, ProcessHtml(sHBody, AtchList); kısmını yapamadım, sizin örnekleri de indiremedim. yardımcı olursanız sevinirim. Mehmet mdagli2003@gmail.com Quote
Sherzod Posted February 12, 2019 Posted February 12, 2019 Hello, Which edition and build of UniGUI are you using ? Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.