Following is my code for the smtp client for sending email
VAR SMTP : TIdSMTP;
MSG : TIdmessage;
begin
MSG:=TIdmessage.Create(NIL);
TRY
WITH MSG.Recipients.Add DO BEGIN
Name:='me025';
Address:='me025#gmail.com'
END;
MSG.BccList.Add.Address:='me025#yahoo.com';
MSG.From.Name:='self025';
MSG.From.Address:='self025#127.0.1.1';
MSG.Body.Text:='<Message Body>';
MSG.Subject:='<Subject of message>';
SMTP:=TIdSMTP.Create(NIL);
TRY
SMTP.Host:='127.0.1.1'; // IP Address of SMTP server
// 127.0.1.1
SMTP.Port:=25; // Port address of SMTP service (usually 25)
SMTP.Connect;
TRY
SMTP.Send(MSG)
FINALLY
SMTP.Disconnect
END
FINALLY
SMTP.Free
END
FINALLY
MSG.Free
END;
end;
which will use a SMTPserver in same pc
the smtp server is a working indy 10 unofficial sample
http://indy.fulgan.com/ZIP/Indy10demo.zip
whenever i connect to the server "Socket error # 11001 Host not found " error occers
but smtp server is receiving all the parameters correctly and showing correctly on the GUI
Has your PC an address of 127.0.1.1 or are you trying to use localhost (127.0.0.1)? People should get used to DNS names... as soon as IPv6 will become mainstream at least people won't be able any longer to remember IP numbers easily :)
Related
I am attempting to create a SOCKS 4/5 server, and I would like to use the Indy TIdSocksServer component as the foundation. It seems straight forward enough and simple to use, but I must be missing something.
I dropped a TIdSocksServer onto a new Form and configured the following:
Active: True
AllowSocks4: True
AllowSocks5: True
Bindings: 0.0.0.0:43334
Default Port: 80
Intercept: null
IOHandler: null
I added code to display 'connect' in a TMemo upon connection:
procedure TForm1.IdSocksServer1Connect(AContext: TIdContext);
begin
Memo1.Lines.Add('connect');
end;
I configured ProxyChains on a Linux host:
/etc/proxychains.conf
...
socks5 10.0.0.56 43334
When I execute the App and try to connect using ProxyChains, I get the following error:
kelly#ubuntu:~/home$ proxychains curl www.google.com
ProxyChains-3.1 (http://proxychains.sf.net)
|DNS-request| www.google.com
|S-chain|-<>-10.0.0.56:43334-<><>-4.2.2.2:53-<--timeout
|DNS-response|: www.google.com does not exist
curl: (6) Could not resolve host: www.google.com
I can confirm that the connection is established, because the text 'connect' gets added to the Memo. I also used Wireshark and observed the three-way handshake and teardown between my Ubuntu host and the Windows host.
It seems the issue is that the traffic is reaching the SOCKS server, but not getting forwarded. I acknowledge that this is absolute minimum code, but I am under the impression that the TIdSocksServer component would take care of forwarding the traffic, and I would add in supporting functions such as validating credentials for SOCKS5, etc.
Remy identified the issue with my code. In order to verify that the server was receiving connections I added a procedure which wrote to a TMemo component, which was causing a deadlock. To fix the error all I had to do was remove the procedure which was updating the TMemo component. Works as expected.
TWebRequest has two metnod for retrive the client IP Address:
RemoteIP
RemoteAddr
From docs of RemoteIP:
Specifies the IP of the remote target machine associated with the HTTP
request message. Read the RemoteIP property to obtain the IP address
of the remote target machine associated with the HTTP request message.
From docs of RemoteAddr:
Indicates the remote IP address of the client associated with the HTTP
request message. Read RemoteAddr to obtain the IP address of the
source of the Web client request.
They seem very close but RemoteIP return an empty string.
I want retrieve the client ip address, what is the right method?
If we look into source code we will find the following in the declaration of TWebRequest
property RemoteIP: string read GetRemoteIP;
property RemoteAddr: string index 21 read GetStringVariable;
Implementation:
function TWebRequest.GetRemoteIP: string;
begin
Result := EmptyStr;
end;
and GetStringVariable is a virtual method.
Let's look into one of child classes - TISAPIRequest, we will find the following:
LResult := GetFieldByNameA(ServerVariables[Index]);
ServerVariables[21] is 'REMOTE_ADDR' header, which shows IP of client or proxy server.
But there is no implementation for GetRemoteIP.
It looks like RemoteIP isn't used in requests, because TCGIRequest, TApacheRequest and TWinCGIRequest also don't implement GetRemoteIP.
I'm having a very strange problem sending emails via indy through two different mechanisms in my program. This problem is similar to [this one][1], but not exactly the same. I'm using Indy 10.5 with the latest OpenSSL libraries and Delphi XE3.
The first code snippet, which works, is a simple SMTP client I wrote. Here's an example of how I set it up. This isn't the exact code but it should give you an idea.
FIndySMTP.Intercept := FIndyLogFile;
FIndySMTP.IOHandler := FIndySSLHandler;
FIndyMessage.From.Address := FEmailAddress;
FIndySSLHandler.Destination := FSMTPAddress + ':' + IntToStr(FSMTPPort);
FIndySSLHandler.Host := FSMTPAddress;
FIndySSLHandler.Port := FSMTPPort;
FIndySMTP.Host := FSMTPAddress;
FIndySMTP.Port := FSMTPPort;
FIndySMTP.Username := FAccountName;
FIndySMTP.Password := FAccountPass;
FIndySMTP.AuthType := satDefault;
FIndySMTP.UseEhlo := True;
FIndySMTP.UseTLS := utUseExplicitTLS
FIndySMTP.Connect;
try
if FIndySMTP.Connected = True then
FIndySMTP.Send(FIndyMessage);
finally
FIndySMTP.Disconnect;
end;
This generates a successful email with the log:
Recv 10/9/2015 10:41:02 AM: 220 server.server1.local Microsoft ESMTP MAIL Service ready at Fri, 9 Oct 2015 13:41:01 -0400<EOL>
Sent 10/9/2015 10:41:02 AM: EHLO DEIMOS<EOL>
Recv 10/9/2015 10:41:02 AM: 250-server.server1.local Hello [68.14.239.173]<EOL>250-SIZE 36700160<EOL>250-PIPELINING<EOL>250-DSN<EOL>250-ENHANCEDSTATUSCODES<EOL>250-AUTH<EOL>250-8BITMIME<EOL>250-BINARYMIME<EOL>250 CHUNKING<EOL>
Sent 10/9/2015 10:41:02 AM: RSET<EOL>
Recv 10/9/2015 10:41:02 AM: 250 2.0.0 Resetting<EOL>
....(The rest snipped)
Now the second method, which uses Report Builder built in Email components to send a Report via email (again, some code is snipped for brevity, the real clue is in the logs):
lIOHandler.Destination := Host + ':' + IntToStr(Port);
lIOHandler.Host := Host;
lIOHandler.Port := Port;
TheReport.EmailSettings.HostAddress := Host;
TheReport.EmailSettings.UserName := UserName;
TheReport.EmailSettings.Password := Password;
lEmail.SMTP.OnEmailError := FMain.EmailErrorEvent;
TppSMTPIndy(lEmail.SMTP).IndySMTP.OnFailedRecipient := FMain.idSMTPFailedRecipient;
TppSMTPIndy(lEmail.SMTP).IndySMTP.Intercept := FMain.IdLogFile1;
TppSMTPIndy(lEmail.SMTP).IndySMTP.Port := Port;
TppSMTPIndy(lEmail.SMTP).IndySMTP.IOHandler := lIOHandler;
TppSMTPIndy(lEmail.SMTP).IndySMTP.UseTLS := utUseExplicitTLS;
TppSMTPIndy(lEmail.SMTP).IndySMTP.AuthType := satDefault;
TppSMTPIndy(lEmail.SMTP).IndySMTP.UseEhlo := True;
TheReport.SendMail;
You can see that with the exception of using the Report Builder TppSMTPIndy, every setting is the same. Yet the email does not get sent, and the log looks like this:
Stat Connected.
Recv 10/9/2015 10:44:31 AM: 220 server.server1.local Microsoft ESMTP MAIL Service ready at Fri, 9 Oct 2015 13:44:28 -0400<EOL>
Sent 10/9/2015 10:44:31 AM: EHLO DEIMOS<EOL>
Recv 10/9/2015 10:44:31 AM: 250-server.server1.local Hello [68.14.239.173]<EOL>250-SIZE 36700160<EOL>250-PIPELINING<EOL>250-DSN<EOL>250-ENHANCEDSTATUSCODES<EOL>250-AUTH<EOL>250-8BITMIME<EOL>250-BINARYMIME<EOL>250 CHUNKING<EOL>
Sent 10/9/2015 10:44:31 AM: QUIT<EOL>
Recv 10/9/2015 10:44:31 AM: 221 2.0.0 Service closing transmission channel<EOL>
Stat Disconnected.
You can see that a QUIT is sent immediately after receiving HELLO. This is why my question is different than the link above. That person was at least receiving a STARTTLS request.
What could be causing Indy to send a QUIT immediately after receiving a HELLO? I am not getting any errors. It just silently fails and the program moves on.
Now here's a kicker hint. If I set the AuthType to satNone in the Report Builder example it works. While in my first example I can set the AuthType to satNone and satDefault and both work.
Any ideas?
Thanks a lot for your time.
What could be causing Indy to send a QUIT immediately after receiving a HELLO?
The only time QUIT is sent is when TIdSMTP.Disconnect() is called.
The only times that TIdSMTP itself calls Disconnect() are when:
an exception is raised inside of TIdSMTP.Connect(), such as if the server's greeting has an error code, or there is a unexpected problem parsing the server's greeting or EHLO response.
an exception is raised inside of TIdSMTP.StartTLS(), which is called by TIdSMTP.Authenticate() (which is called by TIdSMTP.Send() if not already called beforehand). However, since you have set UseTLS=utUseExplicitTLS and the server's EHLO response does not advertise support for STARTTLS, TIdSMTP.StartTLS() is effectively a no-op on this server.
I am not getting any errors. It just silently fails and the program moves on.
Unless Report Builder is catching exceptions internally and not passing them into your code, then the most likely scenario is that Report Builder itself is calling TIdSMTP.Disconnect() without calling TIdSMTP.Send() first. The RSET command shown in your log is sent by TIdSMTP.Send() at the beginning of the email (BTW, more recent versions of Indy no longer send RSET unless the email fails with an SMTP error code). Report Builder is likely just skipping Send(), and I can think of one possible reason why it might do that.
AuthType=satDefault uses the AUTH LOGIN command (which is not a secure command), but your server's EHLO response is not advertising support for LOGIN authentication (in fact, it is not advertising support for any authentications at all). As such, TIdSMTP.Authenticate() will skip authentication on this server by default and return False, and also set the TIdSMTP.DidAuthenticate property to False. Maybe Report Builder is calling TIdSMTP.Authenticate() directly and checking the result before calling TIdSMTP.Send(). Your non-ReportBuilder example does not do that validation. Setting AuthType=satNone will cause TIdSMTP.Authenticate() to return True and set the TIdSMTP.DidAuthenticate property to True.
If the server happens to support LOGIN authentication (some servers do support it without advertising it), you can set the TIdSMTP.ValidateAuthLoginCapability property to False (it is True by default) to make satDefault attempt authentication as long as the TIdSMTP.Username property has been assigned a non-blank string.
This question already has answers here:
Using Gmails Outgoing SMTP from DELPHI(Indy) using TLS
(3 answers)
SendEmail with Indy components
(2 answers)
Closed 9 years ago.
First i have this code and i tried with Gmail Smtp server but i have the result with error exception : Socket °10060 !!!!
it a delay socket error , please if any one tried this before and it work for him just share the idea with me thanks !!!!
VAR SMTP : TIdSMTP; VAR MSG : TIdMSG;
MSG:=TIdMSG.Create(NIL);
TRY
WITH MSG.Recipients.Add DO BEGIN
Name:='<Name of recipient>';
Address:='<Email address of recipient>'
END;
MSG.BccList.Add.Address:='<Email address of Blind Copy recipient>';
MSG.From.Name:='<Name of sender>';
MSG.From.Address:='<Email address of sender>';
MSG.Body.Text:='<Message Body>';
MSG.Subject:='<Subject of message>';
SMTP:=TIdSMTP.Create(NIL);
TRY
SMTP.Host:='x.x.x.x'; // IP Address of SMTP server
SMTP.Port:=25; // Port address of SMTP service (usually 25)
SMTP.Connect;
TRY
SMTP.Send(MSG)
FINALLY
SMTP.Disconnect
END
FINALLY
SMTP.Free
END
FINALLY
MSG.Free
END;
the question is extended from the question which I asked before.
Currently I can let my proxy server with TIdHTTPProxyServer forward the request to another proxy server which also using TIdHTTPProxyServer. But when I tried to let it forward the request to other proxy servers from the free proxy servers list on web. Most servers which can be used through IE proxy setting return 403 error message to my proxy server. In fact I have tried about 20 valid proxy servers, but only two can accept the requests from my proxy server. I can not figure out why it happens.
Below is the code I use in HTTPBeforeCommand of TIdHTTPProxyServer.
TIdIOHandlerStack* tempIO = new TIdIOHandlerStack(AContext->OutboundClient);
TIdConnectThroughHttpProxy* tempProxy = new TIdConnectThroughHttpProxy(AContext->OutboundClient);
tempProxy->Enabled = true;
tempProxy->Host = ProxyServerAddress;
tempProxy->Port = ProxyServerPort ;
tempIO->TransparentProxy = tempProxy;
AContext->OutboundClient->IOHandler = tempIO;
After monitoring the behaviors of TIdHTTPProxyServer using wireshark, I found TIdHTTPProxyServer always send a CONNECT request to other proxy servers at first berfore foward the real requests(the browser does not do that).
And then receive 403 response for most proxy servers. But still do not know how to make it works.
Updated on 2012/08/07
Hi, I am not really familiar with those HTTP stuffs, so I just record what I saw in wireshark here. It seems IE uses GET/POST commands for HTTP requests and CONNECT command for HTTPS requests. And most proxy servers block Connect commands when they are not HTTPS request (For example, CONNECT www.google.com.tw:80 HTTP/1.0). That is why TIdConnectThroughHttpProxy always does not work.
Below is my workaround, I made a little bit changes in IdHTTPProxyServer.pas. Hope it is useful for someone else who meets the same problems.
For CONNECT commands, still use TIdConnectThroughHttpProxy
Within TIdHTTPProxyServer.CommandCONNECT
if UseProxy = True then
begin
tempIO := TIdIOHandlerStack.Create(LContext.FOutboundClient);
tempProxy := TIdConnectThroughHttpProxy.Create(LContext.FOutboundClient);
tempProxy.Enabled := True;
tempProxy.Host := UseProxyAddr;
tempProxy.Port := UseProxyPort ;
tempIO.TransparentProxy := tempProxy;
LContext.FOutboundClient.IOHandler := tempIO;
end;
For GET/POST commands, I should directly send GET www.google.com.tw:80 HTTP/1.0 to other proxy servers instead of sending CONNECT www.google.com.tw:80 HTTP/1.0 at first.
Within TIdHTTPProxyServer.CommandPassThrough
if UseProxy = True then
begin
TIdTCPClient(LContext.FOutboundClient).Host := UseProxyAddr;
TIdTCPClient(LContext.FOutboundClient).Port := UseProxyPort;
end else
begin
TIdTCPClient(LContext.FOutboundClient).Host := LURI.Host;
TIdTCPClient(LContext.FOutboundClient).Port := IndyStrToInt(LURI.Port, 80);
end;
Also within TIdHTTPProxyServer.CommandPassThrough, I should let header Proxy-Connection = close
LContext.Connection.IOHandler.Capture(LContext.Headers, '', False);
LContext.Headers.Values['Proxy-Connection'] := 'close';
Finally within TIdHTTPProxyServer.TransferData
if AContext.TransferSource = tsClient then
begin
if UseProxy = True then
begin
ADest.IOHandler.WriteLn(AContext.Command + ' ' + AContext.Target + ' HTTP/1.0');
end else
begin
ADest.IOHandler.WriteLn(AContext.Command + ' ' + AContext.Document + ' HTTP/1.0');
end;
end;
It is my first time to implement delphi, and hope there are better solutions.
I believe you should not use pin-holing - http://www.indyproject.org/docsite/html/TIdConnectThroughHttpProxy.html
CONNECT command is not how WWW works. No browser use it. It is how non-WWW programs try to break-through the firewalls and open direct access to all areas of internet beyond WWW.
Don't use "transparent proxy" classes.
Use regular HTTP proxy, like in How to download a file over HTTPS using Indy 10 and OpenSSL?
BTW, there is no such event handler as u name "HTTPBeforeCommand"
http://www.indyproject.org/docsite/html/!!MEMBEROVERVIEW_TIdHTTPProxyServer.html