9

I am having issues posting to Amazon's SES Service using Indy's TIdHTTP.

Here is an example of the code i am using:

procedure TMainFrm.btnAmazonSESClick(Sender: TObject);
var
  SSLHandler: TIdSSLIOHandlerSocket;
  HttpClient: TIdHTTP;  
  Params: TStringStream;
begin
  SSLHandler := TIdSSLIOHandlerSocket.Create(Self);
  HttpClient := TIdHTTP.Create(Self);  
  Params := TStringStream.create('');
  try
    with SSLHandler do
      SSLOptions.Method := sslvSSLv3
    with HttpClient do
    begin
      IOHandler := SSLHandler;
      AllowCookies := True;
      HandleRedirects := True;
      HTTPOptions := [hoForceEncodeParams];
      Request.ContentType := 'application/x-www-form-urlencoded';
    end;

    PageMemo.Text := HttpClient.Post('https://email.us-east-1.amazonaws.com?Action=VerifyEmailAddress&AWSAccessKeyId=012Some123Key46&EmailAddress=test@test%2Ecom', Params);

  finally
    SSLHandler.Free;
    HttpClient.Free; 
    Params.Free;
  end;
end;

Result

  • Under Indy 10.5.7 I get the error: HTTP/1.1 404 Not Found

  • Under Indy 9.0.14 I get the error: Socket Error # 11004

Debugging Trials

  • This same demo can successfully GET the HTML from an HTTPS web page.

  • If i paste the URL above into a browser it displays the expected XML result.

I would appreciate any advice on the cause.

Zax
  • 471
  • 1
  • 4
  • 14
  • 2
    I believe you need the SSL dll's in the same folder as the application or in windows system32 folder... let me know if you want me to upload the ones I have somewhere, my version is libeay32.dll 1.0.0.4 and ssleay32.dll 1.0.0.4 –  Oct 14 '11 at 04:15
  • 1
    You do not `POST` any `Params`, are you sure you want to communicate with webservice this way? – Premature Optimization Oct 14 '11 at 06:08
  • 1
    @PrematureOptimization everything after ? is param name=value, in this case Action=VerifyEmailAddress&AWSAccessKeyId=012Some123Key46&EmailAddress=test@test%2Ecom –  Oct 14 '11 at 11:25
  • 1
    @Dorin Duminica, not really. query-string <> form-data – Premature Optimization Oct 14 '11 at 22:19
  • @DorinDuminica: Thanks, I have included the latest SSL DLL's in the folder – Zax Oct 14 '11 at 22:23

2 Answers2

3

This post is just an incomplete wild guess.

Maybe Remy might help you to correct it. With the following code I'm getting HTTP/1.1 400 Bad Request but I'm not wondering because the API reference talks about Common Query Parameters where is at least required the digital signature you'll create for the request what I don't know how to do.

I can't test this at all because I have no account there. But I think the

procedure TForm1.Button1Click(Sender: TObject);
var
  HTTPClient: TIdHTTP;
  Parameters: TStrings;
  SSLHandler: TIdSSLIOHandlerSocketOpenSSL;

begin
  SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  HTTPClient := TIdHTTP.Create(nil);
  Parameters := TStringList.Create;

  try
    SSLHandler.SSLOptions.Method := sslvSSLv3;
    SSLHandler.SSLOptions.Mode := sslmUnassigned;

    HTTPClient.IOHandler := SSLHandler;
    HTTPClient.HTTPOptions := [hoForceEncodeParams];
    HTTPClient.Request.ContentType := 'application/x-www-form-urlencoded';

    Parameters.Add('Action=VerifyEmailAddress');
    Parameters.Add('EmailAddress=test@test.com');
    Parameters.Add('AWSAccessKeyId=012Some123Key46');
    Parameters.Add('SignatureVersion=2');
    Parameters.Add('Expires='); // ???
    Parameters.Add('Signature='); // ???

    PageMemo.Text := HTTPClient.Post('https://email.us-east-1.amazonaws.com', Parameters);

  finally
    SSLHandler.Free;
    HTTPClient.Free; 
    Parameters.Free;
  end;
end;
TLama
  • 75,147
  • 17
  • 214
  • 392
  • Thanks I will try that, though I cannot see why I should get a different result between Indy and pasting the same URL into the browser. IOW surely if the problem is due to parameters i should receive their XML failure result?!? – Zax Oct 14 '11 at 22:25
  • @Xaz, for instance Firefox displays the content even if he get `HTTP 400 Bad Request` error. E.g. Internet Explorer tell you that bad request happened and doesn't display the XML content response, Indy works the same, create the error message and throw away the content. The request from your example has wrong parameters; namely [IncompleteSignature](http://docs.amazonwebservices.com/ses/latest/APIReference/index.html?CommonErrors.html) what gives you as described in the table HTTP Status Code = 400 (bad request). – TLama Oct 16 '11 at 15:02
  • Thank you for filling in the gaps in my understanding. I am making good progress now. – Zax Oct 17 '11 at 01:38
  • @TLama: `TIdHTTP` does not throw away the response content if an HTTP error occurs. It exposes it as properties of the raised `EIdHTTPProtocolException` exception instead. – Remy Lebeau Nov 12 '13 at 18:13
  • "*I cannot see why I should get a different result between Indy and pasting the same URL into the browser*" - if you paste `https://email.us-east-1.amazonaws.com?Action=VerifyEmailAddress&AWSAccessKeyId=012Some123Key46&EmailAddress=test@test%2Ecom` into a browser, it is going to send a `GET` request, not a `POST` request, so do the same in Indy, eg: `PageMemo.Text := HttpClient.Get('https://email.us-east-1.amazonaws.com?Action=VerifyEmailAddress&AWSAccessKeyId=012Some123Key46&EmailAddress=test@test%2Ecom');`. Otherwise, put the `name=value` pairs into a `TStringList` and `Post()` that. – Remy Lebeau May 03 '17 at 16:34
  • "*required the digital signature you'll create for the request what I don't know how to do*" - this is explained in Amazon's documentation: [Signature Version 4 Signing Process](http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html). – Remy Lebeau May 03 '17 at 16:43
0

Basically, you need to use the right library, i.e.:

For Indy 10.5.7 use openssl-1.0.1e-i386-win32 or openssl-1.0.1e-x64_86-win64 from http://indy.fulgan.com/SSL/ You may want to download an ssl demo from: http://indy.fulgan.com/ZIP/

Regards

Jose

Jose
  • 1