简体   繁体   English

从Delphi运行外部PHP脚本

[英]Running an external php script from Delphi

Ok - this is in continuation from my earlier question about sending an email using a php script . 好的-这是我先前有关使用php脚本发送电子邮件的问题的延续。 I'm now using PEAR to send the mail. 我现在正在使用PEAR发送邮件。 The php script i use is the following one (successfull if executed alone): PHPEMail.php 我使用的php脚本如下(如果单独执行,则成功): PHPEMail.php

<?php
require_once "Mail.php"; // Pear Mail.php 

$from = "FromName <FromName@SomeAddress.com>";
$to = $_POST["destination"]; // destination  
$subject = "Hello You!";
$body = $_POST["nicebody"]; // body of text sent 
$host = "ValidServerName";
$username = "User";         // validation at server    
$password = "Password";     // validation at server 

$headers = array ('From' => $from,
  'To' => $to,
  'Subject' => $subject);
$smtp = Mail::factory('smtp',
  array ('host' => $host,
    'auth' => true,
    'username' => $username,
    'password' => $password));

$mail = $smtp->send($to, $headers, $body);

if (PEAR::isError($mail)) {
  echo("<p>" . $mail->getMessage() . "</p>");
 } else {
  echo("<p>Message successfully sent!</p>");
 }
?>

I now need to execute this script (PHPEMail.php) from Delphi, passing some variables, using winsock. 现在,我需要使用Winsock从Delphi执行此脚本(PHPEMail.php),并传递一些变量。 I'm going with this code - which has not been successfull up to now: 我正在使用此代码-到目前为止尚未成功:

Procedure SendEmail;
var
  WSADat:WSAData;
  SomeText:TextFile;
  Client:TSocket;
  Info,TheData,Lina,Nicebody:String;
  SockAddrIn:SockAddr_In;
begin
  try
    if not FileExists(Log) then exit;     
    AssignFile(SomeText, Log);             // try to open log, assigned to SomeText
    Reset(SomeText);                       // Reopen SomeText for reading
    while not Eof(SomeText) do
    begin
      ReadLn(SomeText, Lina);             //read each line of SomeTextans place it in linha
      nicebody:=Nicebody+#13#10+Lina;     // nicebody = all line red from SomeText
    end;
    CloseFile(SomeText);                  // SomeText is closed
    DeleteFile(PChar(Log));               // log is deleted
//
    WSAStartUp(257,WSADat);
    Client:=Socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
    SockAddrIn.sin_family:=AF_INET;
    SockAddrIn.sin_port:=htons(80);
    SockAddrIn.sin_addr.S_addr:=inet_addr('66.66.66.66'); // server IP
    if Connect(Client,SockAddrIn,SizeOf(SockAddrIn))=0 then begin
      Info:='destination='+EmailDestAddressFromIni + '' +'Nicebody='+Nicebody;
      TheData:='POST PHPEMail.php HTTP/1.0'                   +#13#10+
             'Connection: close'                              +#13#10+
             'Content-Type: application/x-www-form-urlencoded'+#13#10+
             'Content-Length: '+IntToStr(Length(Info))       +#13#10+
             'Host: someEmailHostAddress'                         +#13#10+
             'Accept: text/html'                              +#13#10+#13#10+
              Info                                            +#13#10;
      Send(Client,Pointer(TheData)^,Length(TheData),0);
      end;
    CloseSocket(Client);
  except
    exit;
  end;
end;

[... more code not related]

I'm pretty sure the fault is in "TheData" that is sent to the web server. 我很确定故障出在发送到Web服务器的“ TheData”中。 The PHP script is just not triggered. PHP脚本只是不触发。 Anyone have an idea what is going wrong? 任何人都知道出什么问题了吗?

(note: i want to use winsock, i don't want third party components. The complete code, which is a server, weight about 12ko and is destinated to be embeded in some hardware). (注意:我想使用Winsock,我不需要第三方组件。完整的代码是一台服务器,重约12ko,注定要嵌入某些硬件中)。

SEE FINAL CODE AT END. 请参阅最终代码。


Because i could not see the POST on the server log i have made some improvement in my code (plus some error message). 因为在服务器日志上看不到POST,所以我对代码进行了一些改进(加上一些错误消息)。 NOW the server's log shows some trace of the packets sent... that is, the usual id and time plus the the lettre "P" ... probably the first letter of the word 'POST' (the Data sent). 现在,服务器的日志显示了一些已发送数据包的痕迹……也就是说,通常的ID和时间加上字母“ P”……可能是单词“ POST”(发送的数据)的首字母。 I thus have to investigate the 'Send()' command. 因此,我必须研究“ Send()”命令。 (i'm on Delphi 2009). (我在Delphi 2009上)。 I get no error from winsock or the send command. 我没有从winsock或send命令得到任何错误。

Procedure SendEmail;

const
  a = #13#10;

var
  WSAData:TWSAData;
  Texto:TextFile;
  ClientSocket :TSocket;
  Info,Data,Lina,Contenu:String;
  host:SockAddr_In;
  i_result:Integer;

begin
  try
    if not FileExists(Log) then exit;     
    AssignFile(Texto, Log);      
    Reset(Texto);  // Reopen texto for reading
    while not Eof(Texto) do
    begin
      ReadLn(Texto, Lina); //read each line of texto and place it in lina
      Contenu:=Contenu+#13#10+Lina;  // contenu is all lines of texto
    end;
    CloseFile(Texto); // close texto
    DeleteFile(PChar(Log)); // delete log


    // Initialize Winsock
    i_result := WSAStartUp(257,WSAData);
    if (i_Result <> NO_ERROR) then
    begin
     MessageBox(0,'Initialization of winsock failed.','Error',MB_OK Or MB_ICONERROR);
     Exit;
    end;

    // Create a SOCKET for connecting to server
    ClientSocket := Socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
    If ClientSocket = INVALID_SOCKET Then
    begin
     MessageBox(0,'ServerSocket creation failed.','Error',MB_OK Or MB_ICONERROR);
     WSACleanUp;
     Exit;
    end;

    // The sockaddr_in structure specifies the address family,
    // IP address, and port of the server to be connected to.
    host.sin_family:=AF_INET;
    host.sin_port:=htons(80);
    host.sin_addr.S_addr:=inet_addr('77.66.66.66');

    // Connect to server.
    i_result:= Connect(ClientSocket,host,SizeOf(host));
    if i_result = SOCKET_ERROR then
    begin
     MessageBox(0,'Failed to connect to remote computer.','Error',MB_OK Or MB_ICONERROR);
     WSACleanUp;
     Exit;
    end
    else
    begin

      Info := 'destination=' + UrlEncode(CFG.Email) + '&' + 'contenu=' + UrlEncode(contenu);
      Data:='POST /pearemail.php HTTP/1.0'                    +#13#10+
             'Connection: close'                              +#13#10+
             'Content-Type: application/x-www-form-urlencoded'+#13#10+
             'Content-Length: '+IntToStr(Length(Info))        +#13#10+
             'Host: mail.tatata.com'                            +#13#10+
             'Accept: text/html'                              +#13#10+#13#10+
              Info+#13#10;

      // Send buffer
       i_result := Send(ClientSocket,Pointer(Data)^,Length(Data),0);
       if (i_result = SOCKET_ERROR) then
       MessageBox(0,'Failed to send to remote computer.','Error',MB_OK Or MB_ICONERROR);
       closesocket(ClientSocket);
       WSACleanup;
       Exit;

    end;
       // shutdown the connection since no more data will be sent
       i_result:= shutdown(ClientSocket, SD_SEND);
       if (i_Result = SOCKET_ERROR) then
       MessageBox(0,'Shutdown failed.','Error',MB_OK Or MB_ICONERROR);
       closesocket(ClientSocket);
       WSACleanup();
       Exit;

  except
    exit;
  end;
end;

pearemail.php script waiting for the POST: pearemail.php脚本等待POST:

<?php
require_once "Mail.php";

$from = "name <name@tatata.com>";
$to = $_POST["destination"];
$subject = "Number 2!";
$body = $_POST["contenu"];
$host = "mail.server.com";
$username = "user";
$password = "password";

$headers = array ('From' => $from,
  'To' => $to,
  'Subject' => $subject);
$smtp = Mail::factory('smtp',
  array ('host' => $host,
    'auth' => true,
    'username' => $username,
    'password' => $password));

$mail = $smtp->send($to, $headers, $body);

if (PEAR::isError($mail)) {
  echo("<p>" . $mail->getMessage() . "</p>");
 } else {
  echo("<p>Message successfully sent!</p>");
 }
?>

The second token of the first HTTP line needs to be an absolute URL path. 第一行HTTP的第二个令牌必须是绝对URL路径。 It needs to start with a slash. 它需要以斜杠开头。

POST /PHPEMail.php HTTP/1.0

You should also make some effort to ensure that the data you send really is URL-encoded, as the content-type says it is. 您还应该做出一些努力,以确保您发送的数据确实是URL编码的(如内容类型所说的那样)。 Characters 10 and 13 are not valid characters in a URL. 字符10和13在URL中不是有效的字符。 You also need to consider all the characters in the text file you're reading: 您还需要考虑正在读取的文本文件中的所有字符:

Info := 'destination=' + UrlEncode(EmailDestAddressFromIni) +
  '&' + 'Nicebody=' + UrlEncode(Nicebody);

I notice that you're not reading the response from the server. 我注意到您没有从服务器读取响应。 Don't ignore that. 不要忽略这一点。 Sometimes it may tell you what's wrong. 有时它可能会告诉您出了什么问题。 I also saw no mention of what the server logs said had occurred when you tried to run your code. 当您尝试运行代码时,我也没有提到服务器日志所说的内容。

You're bound to make more mistakes like this along the way. 这样一来,您肯定会犯更多的错误。 Consider using a library that handles this sort of stuff for you, such as Indy , ICS , or Synapse . 考虑使用一个为您处理此类内容的库,例如IndyICSSynapse Don't re-implement HTTP unless you really have to. 除非确实需要,否则不要重新实现HTTP。 And if you really don't want third-party code, consider second-party code (or is it first-party?) by using the stuff built in to Windows. 而且,如果您确实不希望使用第三方代码,请使用Windows内置的内容考虑使用第二方代码(或者是第一方代码)。 KB 165298 has a short example of using InternetConnect , HttpOpenRequest , and HttpSendRequest to post a URL-encoded form request. 知识库文章165298有一个使用InternetConnectHttpOpenRequestHttpSendRequest来发布URL编码的表单请求的简短示例。

As I see from your Delphi code, all information of the email has been packed into one variable, but in your php script how do pass it your many php variables? 正如我从您的Delphi代码中看到的那样,电子邮件的所有信息都打包到一个变量中,但是在您的php脚本中,如何将许多php变量传递给它? You have to unpack/parse it to pass each variable (target address, subject, mail body etc) in your php script. 您必须解压缩/解析它以在您的php脚本中传递每个变量(目标地址,主题,邮件正文等)。 (In your current php script there are many $_posts, but it receives only 1 actual post from Delphi code.) (在您当前的php脚本中,有许多$ _posts,但它仅从Delphi代码中收到1条实际的帖子。)

Below is my working code to a php script. 下面是我的PHP脚本工作代码。

result := 'POST /index.php HTTP/1.1' +
a + 'Host: somehost.com' +
a + 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080406 K-Meleon/1.1.5' +
a + 'Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5' +
a + 'Accept-Language: en-us,en;q=0.5' +
a + 'Accept-Encoding: gzip,deflate' +
a + 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7' +
a + 'Keep-Alive: 300' +
a + 'Connection: keep-alive' +
a + 'Referer: http://somehost.com/index.php' +
a + 'Content-Type: application/x-www-form-urlencoded' +
a + 'Content-Length: 73' + a +
a + 'link=' + MyHttpEnCodedStrData  + a + a;

a is #13#10. a是#13#10。

Another important thing is "link='; it is the variable name in my php script that receives/holds the data I'm sending. Since I'm sending only 1 variable, and it is not email script, no php parsing needed, so I didn't paste my php code here. 另一个重要的事情是“ link =”;它是我的php脚本中的变量名称,用于接收/保存我发送的数据。由于我仅发送1个变量,并且它不是电子邮件脚本,因此不需要php解析,所以我没有在这里粘贴我的PHP代码。

Hope I made it clear :) 希望我说清楚了:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM