2009-05-26 199 views
0
運行的外部PHP腳本

好了 - 這是從我前面的問題有關sending an email using a php script延續。我現在使用PEAR發送郵件。 PHP腳本我用的是下面的一個(全成如果單獨執行):PHPEMail.php德爾福

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

$from = "FromName <[email protected]>"; 
$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>"); 
} 
?> 

我現在需要執行從德爾福這個腳本(PHPEMail.php),傳遞一些變量,用winsock。我這個代碼去 - 這還沒有被全成到現在:

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] 

我敢肯定,故障是在「海圖」發送到Web服務器。 PHP腳本沒有被觸發。任何人有一個想法是什麼問題? (注意:我想使用winsock,我不想要第三方組件。完整的代碼,這是一個服務器,重量約12ko,並且被註定要嵌入到某些硬件中)。

查閱最終代碼月底。


,因爲我無法看到服務器日誌我有我的代碼做了一些改進(加上一些錯誤信息)的POST。現在,服務器的日誌顯示了一些發送的數據包的蹤跡...也就是說,通常的ID和時間加上了字母「P」......可能是單詞「POST」(數據發送)的第一個字母。因此我必須調查'Send()'命令。 (我在德爾福2009年)。我從winsock或發送命令沒有錯誤。

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腳本等待POST:

<?php 
require_once "Mail.php"; 

$from = "name <[email protected]>"; 
$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>"); 
} 
?> 
+0

要carefaul,你的PHP代碼將垃圾郵件發送者濫用,如果你把它放到網上的方式,是 – julioc 2009-05-27 18:48:17

回答

2

第一HTTP線的第二令牌需要是絕對URL路徑。它需要以斜槓開始。

 
POST /PHPEMail.php HTTP/1.0 

您還應該努力確保您發送的數據真的是URL編碼的,正如內容類型所說的那樣。字符10和13在URL中不是有效的字符。您還需要考慮所有的字符,你正在閱讀的文本文件:

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

我注意到,你不是從服務器讀取響應。不要忽視這一點。有時它可能會告訴你什麼是錯的。當您嘗試運行您的代碼時,我也沒有看到提及服務器日誌所發生的情況。

你肯定犯更多的錯誤這樣一路走來。考慮使用處理這種東西的庫,例如Indy,ICSSynapse。除非你真的必須重新實現HTTP。如果你真的不想要第三方代碼,可以考慮使用Windows內置的東西來考慮第二方代碼(或者它是第一方?)。 KB 165298具有使用InternetConnectHttpOpenRequestHttpSendRequest後一個URL編碼形式請求的短的例子。

+0

謝謝服務器錯誤日誌沒有說什麼 - 甚至沒有連接顯示!我應該用一些
取代chr 10和13?我嘗試過Indy,ICS和Synapse,每臺服務器的結果都超過600ko - 這對我來說太重要了整個服務器放在資源中。實際代碼大約是12-20ko最大。我會看看KB 165298. – volvox 2009-05-26 03:10:01

+0

但我知道它連接。在「如果連接」之後的某個時候添加ShowMessage,我可以讀取發送的數據,即目標電子郵件和NiceBody(數據)。乍一看,該數據看起來非常合適。 – volvox 2009-05-26 03:20:54

2

當我從你的Delphi代碼看,電子郵件的所有信息已經被打包成一個變量,但在你的PHP腳本如何通過它的許多PHP變量?你必須解壓縮它,以便在你的php腳本中傳遞每個變量(目標地址,主題,郵件正文等)。(在你當前的php腳本中有許多$ _posts,但它只能從Delphi代碼中接收1個實際的帖子。)

下面是我對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是#13#10。

另一個重要的事情是「link =';它是我的php腳本中的變量名稱,它接收/保存我發送的數據,因爲我只發送1個變量,並且不是電子郵件腳本, PHP解析需要,所以我沒有在這裏貼上我的PHP代碼。

希望我清楚:)