Use SSL with Delphi yet still having a single exe
We use Indy and we need SSL eMail support in our app., however we need to have our application in a single .Exe.
We 开发者_开发百科know that the default Indy handler requires to have the dlls in the path. Extracting the Dlls from one of the EXE's resources would be the last resort.
Any better ideas?
Try SSLBlackBox.
TOndrey gave you a good answer. I use SecureBlackBox as well. You may consider some other third party components:
- StreamSec
- SecureBridge from DevArt
Be aware: if you add SSL/TLS support inside your executable, it might become restricted for export. If you're in the USA, this could mean that your application cannot be sold or given to people outside the USA. This is why these DLL's aren't part of Indy or Delphi themselves.
The libraries that Delphi uses are actually compiled DLL's from the OpenSSL project. But if you have a good knowledge of C then you should be able to compile the source to .obj files and link them with your Delphi code instead. You would probably need to modify part of the Indy code for this too. Of course, others could have done this too, but that makes the export of those Indy components (or even Delphi itself) more complex, because of those export restrictions.
Funnily enough, source code is protected by the first amendment which basically allows you to print the code in a book and then send it to some rogue nation. While if you'd send it in digital form (compiled or not) then you're committing a federal offence and probably will have to be careful when picking up the soap in the shower for at least a year... No one claimed that laws make sense. They can just be a pain in the [beep]...
Other SSL solutions don't work together with the Indy components, which would mean you'd have to rewrite part of your code to support those other solutions.
This link tells how you can load a DLL from memory, so you don't need to have it on disk. It's an alternate solution which I haven't tried. I don't think it will work, since the two DLL's depend on each other, but it might be worth a try...
Is the "Single EXE" requirement for distribution purposes or must it also be a single .EXE file when running on the client's machine?
If it's only for distribution purposes, you can append the DLL files to the end of your .EXE file and then - when the program starts - extract them from the .EXE file and store them locally as .DLL files, something like this:
VAR F,O : FILE;
VAR BUF : ARRAY[1..<MaxSizeOfDLLs>] OF BYTE;
ASSIGN(F,ParamStr(0)); RESET(F,1);
SEEK(F,<OriginalExeSize>);
BLOCKREAD(F,BUF,<FirstDllSize>);
ASSIGN(O,<NameOfFirstDLL>); REWRITE(O,1);
BLOCKWRITE(O,BUF,<FirstDllSize>); CLOSE(O);
BLOCKREAD(F,BUF,<SecondDllSize>);
ASSIGN(O,<NameOfSecondDLL>); REWRITE(O,1);
BLOCKWRITE(O,BUF,<SecondDllSize>); CLOSE(O);
SEEK(F,<OriginalExeSize>); TRUNCATE(F); CLOSE(F)
Quick'n'Dirty, not properly formatted, etc., but should give you the basic idea.
Have you tried compiling the OpenSLL source yourself and importing the object files into Delphi?
Recommended reading: Using C object files in Delphi - explains how to create a program that does not need a DLL, and can be deployed in one piece
I use Microsoft's CAPICOM for SSl3 and it solved my needs... It's freely redistributable but discontinued
If you try other components maybe you should look to SYNAPSE(at http://synapse.ararat.cz/) (I also use) it can work with StreamSec(and others) to send emails over ssl. Its free and easy to work.
Const
cdoSendUsingMethod = 'http://schemas.microsoft.com/cdo/configuration/sendusing';
cdoSMTPServer = 'http://schemas.microsoft.com/cdo/configuration/smtpserver';
cdoSMTPServerPort = 'http://schemas.microsoft.com/cdo/configuration/smtpserverport';
cdoSendServerPort = '25';
cdoSendUsingPort = 2;
cdoSMTPConnectionTimeout = 'http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout';
cdoSMTPAuthenticate = 'http://schemas.microsoft.com/cdo/configuration/smtpauthenticate';
cdoAnonymous = '0';
cdoBasic = '1';
cdoSMTPUseSSL = 'http://schemas.microsoft.com/cdo/configuration/smtpusessl';
cdoSendUserName = 'http://schemas.microsoft.com/cdo/configuration/sendusername';
cdoSendPassword = 'http://schemas.microsoft.com/cdo/configuration/sendpassword';
cdoURLGetLatestVersion = 'http://schemas.microsoft.com/cdo/configuration/urlgetlatestversion';
...
function SensCDOMail (ASubject, AFrom, ATo, ABody, ASmtpServer : WideString): String;
var
cdoMessage:OleVariant;
cdoConfiguration: OleVariant;
begin
//Configuration Object
cdoMessage:= CreateOleObject('CDO.Message');
cdoConfiguration:= CreateOleObject('CDO.Configuration');
try
cdoConfiguration.Fields(cdoSendUsingMethod):= cdoSendUsingPort;
cdoConfiguration.Fields(cdoSMTPServer):= ASmtpServer;
cdoConfiguration.Fields(cdoSMTPServerPort):= cdoSendServerPort;
cdoConfiguration.Fields(cdoSMTPAuthenticate):= cdoAnonymous;
cdoConfiguration.Fields(cdoSMTPUseSSL ):= True; // use SSL
cdoConfiguration.Fields.Update;
cdoMessage.Configuration:= cdoConfiguration;
cdoMessage.To := ATo;
cdoMessage.From := AFrom;
cdoMessage.Subject := ASubject;
//cdoMessage.HTMLBody := ABody; //Want to send in Html format
cdoMessage.TextBody := ABody; //Want to send in text format
cdoMessage.Send;
finally
VarClear(cdoMessage);
VarClear(cdoConfiguration);
end;
end;
It is possible to include these DLLs into the program's executable as resources and either export them to files when used or even use them without exporting them first by relocating the code and searching the entry points in memory. I have got code somewhere for doing the latter....
精彩评论