好的 - 这是我之前关于sending an email using a php script的问题的延续。我现在正在使用PEAR发送邮件。我使用的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>");
}
?>
我现在需要从Delphi执行这个脚本(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服务器的“TheData”中。 PHP脚本不会被触发。任何人都知道出了什么问题?
(注意:我想使用winsock,我不想要第三方组件。完整的代码,这是一个服务器,重量约为12ko,并且预定在一些硬件中嵌入)。
最后查看最终版代码。
因为我无法在服务器日志上看到POST,所以我的代码有所改进(加上一些错误信息)。现在服务器的日志显示了一些发送的数据包的痕迹......也就是说,通常的id和时间加上lettre“P”...可能是“POST”一词的第一个字母(发送的数据)。因此,我必须调查'Send()'命令。 (我在Delphi 2009上)。我从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;
等待POST的pearemail.php脚本:
<?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>");
}
?>
答案 0 :(得分:2)
第一个HTTP行的第二个标记需要是绝对URL路径。它需要以斜线开头。
POST /PHPEMail.php HTTP/1.0
您还应该努力确保您发送的数据确实是URL编码的,正如内容类型所说的那样。字符10和13不是URL中的有效字符。您还需要考虑正在阅读的文本文件中的所有字符:
Info := 'destination=' + UrlEncode(EmailDestAddressFromIni) +
'&' + 'Nicebody=' + UrlEncode(Nicebody);
我注意到你没有从服务器上读取响应。不要忽视这一点。有时它可能会告诉你什么是错的。我还没有看到当您尝试运行代码时服务器日志所说的内容。
你一定会犯这样的错误。考虑使用为您处理此类内容的库,例如Indy,ICS或Synapse。除非你真的需要,否则不要重新实现HTTP。如果你真的不想要第三方代码,可以使用Windows内置的东西来考虑第二方代码(或者它是第一方?)。 KB 165298有一个使用InternetConnect
,HttpOpenRequest
和HttpSendRequest
发布网址编码表单请求的简短示例。
答案 1 :(得分: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代码。
希望我明确表示:)