使用PHP脚本接收MMS消息

注意:可通过以下链接下载本节中引用的PHP脚本:  http://www.zgbianpofanghuwang.com/download/php2waymms.zip

NowSMS是用于快速开发交互式SMS应用程序和服务的流行工具。在NowSMS产品中,我们将此称为2向SMS。通过2向SMS工具,当NowSMS收到一条SMS消息时,可以将其配置为将该消息分派到HTTP服务器上运行的脚本,本地可执行程序,本地脚本或批处理文件。这提供了一种将收到的消息放入应用程序中的简单方法,以便应用程序可以对消息执行自定义处理。应用程序可以生成对接收到的消息的简单回复,或者执行更高级的应用程序特定逻辑。可以用流行的Web服务器脚本语言(例如PHP,ASP和Perl)编写处理接收到的消息的脚本,从而使这些脚本的开发对于Web开发人员而言是相对简单的过程。

NowSMS还支持将收到的MMS消息路由到应用程序的功能。但是,从历史上看,与SMS相比,开发支持接收MMS消息的应用程序要困难得多。复杂性增加的主要原因是MMS消息的内容比SMS文本消息的内容复杂得多,因为单个MMS消息可以包含多个不同类型的内容对象。

NowSMS过去一直支持三种将接收的MMS消息传递到应用程序的技术:

  • 基于文件/目录的界面,新接收的MMS消息被放置在NowSMS服务器上的目录中。头文件包含MMS消息头的文本版本,以及指向包含MMS消息内容(文本,图像,视频等)的单独文件的指针。
  • HTTP POST上的XML / SOAP接口,其中MMS消息内容根据3GPP定义的MM7格式打包。
  • 一个基于电子邮件的界面,在该界面中,MMS消息内容被重新打包为电子邮件格式,并被路由到指定的电子邮件地址。

Receiving 彩信via HTTP File Upload Post

从2006年10月30日(2006.10.30)的NowSMS 2006版本开始,增加了一种用于双向MMS的新技术。该技术使用HTTP POST将接收到的MMS消息内容传输到在另一台Web服务器上运行的脚本文件中。使用的HTTP POST格式与用于HTML表单中的“ HTTP文件上载”(多部分/表单数据)的格式相同,并特别考虑了使用PHP脚本语言处理HTTP POST的注意事项。该技术不是特定于PHP的,我们希望将来提供其他脚本语言的示例。

收到MMS消息后,可以将NowSMS配置为执行HTTP文件上载到可配置URL的操作。 HTTP File Upload POST的格式类似于Now SMS&如本节所述,由NowSMS Web界面中的“发送MMS消息”表单使用的MMS专有URL提交格式。 现在短信&MMS专有URL提交.

将此HTTP文件上传帖子与Now SMS进行比较时,应注意两个重要区别&MMS专有URL提交格式:

  • 一个 MMSText 变量在HTTP文件上传帖子中不存在。 MMS消息的任何文本部分都将作为MIME类型为“文本/纯文本”的文件组件发布。
  • 彩信文件 变量被替换为 彩信文件 [] 在HTTP File Upload Post中,以允许PHP脚本将变量作为数组处理。 (从2006.10.30版本开始,NowSMS在使用专有URL提交格式时,还将接受MMSFile []作为MMSFile的别名。)

原始HTTP文件上传帖子看起来类似于以下内容:

POST /mmsreceive.php HTTP/1.0

Host: x.x.x.x

Content-type: multipart/form-data; boundary="--boundary-border--"

Content-length: xxxxx (size of content part of post, everything after HTTP header)

Connection: close

Authorization: username:password (base64 encoded)



----boundary-border--

Content-Disposition: form-data; name="PhoneNumber"



+44123456789

----boundary-border--

Content-Disposition: form-data; name="MMSFrom"



+44987654321

----boundary-border--

Content-Disposition: form-data; name="MMSSubject"



Message Subject

----boundary-border--

Content-Disposition: form-data; name="彩信文件 []"; filename="original-filename.ext"

Content-type: Mime/Type



File data goes here

----boundary-border--

Content-Disposition: form-data; name="彩信文件 []"; filename="original-filename2.ext"

Content-type: Mime/Type



The 彩信文件 [] part may be repeated for multiple objects within the 彩信message.

----boundary-border----

的 URL to which the data is posted (http://x.x.x.x/mmsreceive.php in the above example) is configurable.

实际的MIME“ boundary =”值将有所不同。

“ Content-Length:”标头是指HTTP POST内容部分(即,HTTP标头后面的所有内容)的字节大小。

仅当在NowSMS配置中为POST配置了用户名/密码时,“ Authorization:”标题才会出现。

“ PhoneNumber”变量包含消息接收者的电话号码(如果正在通过调制解调器接口接收消息,则通常与GSM / GPRS调制解调器关联的电话号码)。

“ MMSFrom”变量包含消息发件人地址。

“ MMSSubject”变量包含MMS消息的主题。

“ 彩信文件 []”变量包含MMS消息中各个对象的原始文件内容,并且可以重复多次。

彩信HTTP文件上传帖子的PHP处理(mmsreceive.php)

PHP提供了用于处理HTTP文件上传帖子的内置功能。 PHP手册中标题为“处理HTTP文件上载”的一章中对此功能进行了说明,目前可在以下位置在线访问该手册: http://php.net/manual/en/features.file-upload.php.

全局$ _FILES数组提供对文件上载的访问,而move_uploaded_file函数使您可以将上载的文件的副本保存到另一个位置。请特别注意PHP手册中显示上传文件数组的示例,因为这是用于处理MMS消息的多个“ MMSFILE”组件的技术。

以下是一个示例PHP脚本,该脚本处理收到的MMS消息并生成一个简单的HTML博客,其中包含远程用户提交的所有图像和其他内容,每个用户都有自己的博客。该PHP脚本(mmsreceive.php)可以作为ZIP文件的一部分下载,网址为: http://www.zgbianpofanghuwang.com/download/php2waymms.zip.


<?php /* Replace the directory below with the directory that you wish to store received 彩信messages in */ $upload_path = "c:\\upload\\"; /* By default, the script will return an HTTP 500 error if there are any internal processing errors, such as a problem creating a directory or file. Returning an error in this way can signal the submitting application that there is a problem and that it may need to retry. However, it can make it difficult to debug problems when testing submissions via a web form. Set this variable to False to disable the returning of an HTTP 500 error code. */ $returnHttp500OnError = True; /* Variables used by script */ $errorFlag = False; /* Set to True if an error has occurred */ $dateString = date("YmdHis"); /* 彩信images will be stored in a temporary directory name based upon current date/time */ $savedImageFile = False; /* If an error occurs, or the message is text only, delete the temporary directory */ /* MMSFrom variable contains the sender phone number - REQUIRED */ if (!isset($_REQUEST['MMSFrom']) || !$_REQUEST['MMSFrom']) { echo "ERROR: MMSFrom variable (sender) is not set"; $errorFlag = True; } /* MMSSubject variable contains the message subject - if not set, use default text */ if (!isset($_REQUEST['MMSSubject']) || !$_REQUEST['MMSSubject']) { $MMSSubject = "Multimedia Message"; } else { $MMSSubject = $_REQUEST['MMSSubject']; } /* Validate that there is one or more HTTP file upload in the 彩信文件 [] array */ if (!$errorFlag) { $errorFlag = True; /* Default to returning an error, unless we find a valid HTTP file upload */ if ($_FILES["彩信文件"] && is_array($_FILES["彩信文件"]) && count($_FILES["彩信文件"])) { foreach ($_FILES["彩信文件"]["error"] as $key => $error) { if ($error == UPLOAD_ERR_OK) { $errorFlag = False; /* reset error condition, found a valid HTTP file upload */ } } } if ($errorFlag) { echo "ERROR: Request does not include any uploaded files!"; } } /* Build a directory for each user beneath the $upload_path, verify that we have rights to create a temporary file in this user directory */ if (!$errorFlag) { $user_path = $upload_path . $_REQUEST['MMSFrom']; if (!@file_exists ($user_path)) { @mkdir ($user_path); } $user_path = $user_path . "\\"; $tmp_filename = $user_path . "temp.tmp"; $tmp_handle = @fopen ($tmp_filename, "w+"); if (!$tmp_handle) { if ($returnHttp500OnError) header("HTTP/1.0 500 Internal Error"); echo "ERROR: Cannot create files in upload directory " . $user_path; $errorFlag = True; } else { fclose ($tmp_handle); @unlink ($tmp_filename); } } /* Build a temporary directory beneath the user directory for storing image files associated with this 彩信message */ if (!$errorFlag) { $image_path = $user_path . $dateString; if (!@file_exists ($image_path)) { @mkdir ($image_path); } $image_path = $image_path . "\\"; $tmp_filename = $image_path . "temp.tmp"; $tmp_handle = @fopen ($tmp_filename, "w+"); if (!$tmp_handle) { if ($returnHttp500OnError) header("HTTP/1.0 500 Internal Error"); echo "ERROR: Cannot create files in upload directory " . $image_path; $errorFlag = True; } else { fclose ($tmp_handle); @unlink ($tmp_filename); } } if (!$errorFlag) { /* msglog.txt contains previous messages posted by this user in HTML format, without HTML headers. If this file exists, we copy it to msglog.tmp, so that we can create a new msglog.txt file with this new message at the top. */ $msglogTxt = $user_path . "msglog.txt"; $msglogTmp = $user_path . "msglog.tmp"; if (@file_exists ($msglogTmp)) { @unlink ($msglogTmp); } if (@file_exists ($msglogTxt)) { if (!@copy ($msglogTxt, $msglogTmp)) { if ($returnHttp500OnError) header("HTTP/1.0 500 Internal Error"); echo "ERROR: Cannot create temporary file in upload directory " . $user_path; $errorFlag = True; } } if (!$errorFlag) { $msglogTxt_handle = @fopen ($msglogTxt, "w+"); if (!$msglogTxt_handle) { if ($returnHttp500OnError) header("HTTP/1.0 500 Internal Error"); echo "ERROR: Cannot create temporary file in upload directory " . $user_path; $errorFlag = True; } } if (!$errorFlag) { /* This is where we take the 彩信message content, and convert it to simple HTML */ fwrite ($msglogTxt_handle, "<!-- Begin message block -->\r\n"); fwrite ($msglogTxt_handle, "<h2>" . $MMSSubject . "</h2>\r\n"); fwrite ($msglogTxt_handle, "<p><small>" . date("F j, Y, H:i") . "</small></p>\r\n"); /* Repeat for each object/file within the 彩信message */ foreach ($_FILES["彩信文件"]["error"] as $key => $error) { if ($error == UPLOAD_ERR_OK) { $tmp_name = $_FILES["彩信文件"]["tmp_name"][$key]; /* If the content is text, put it directly into the HTML */ if (!strcmp (strtolower($_FILES["彩信文件"]["type"][$key]), "text/plain")) { fwrite ($msglogTxt_handle, "<p>" . file_get_contents ($tmp_name) . "</p>\r\n"); echo " 的 file ". basename( $_FILES["彩信文件"]["name"][$key]). " has been uploaded<br/>"; } /* If the content is SMIL, ignore it */ else if (!strcmp (strtolower($_FILES["彩信文件"]["type"][$key]), "application/smil")) { echo " 的 file ". basename( $_FILES["彩信文件"]["name"][$key]). " has been skipped<br/>"; } else { /* If content is an image, reference it with an img tag, otherwise include an a href */ $new_name = $image_path . basename( $_FILES["彩信文件"]["name"][$key]); if (@move_uploaded_file($tmp_name, $new_name)) { $savedImageFile = True; echo " 的 file ". basename( $_FILES["彩信文件"]["name"][$key]). " has been uploaded<br/>"; if (!strncmp (strtolower($_FILES["彩信文件"]["type"][$key]), "image/", 6)) { fwrite ($msglogTxt_handle, "<p><img src=\"" . $dateString . "\\" . basename($_FILES["彩信文件"]["name"][$key]) . "\"/></p>\r\n"); } else if (!strncmp (strtolower($_FILES["彩信文件"]["type"][$key]), "video/", 6)) { fwrite ($msglogTxt_handle, "<p>Video attachment: <a href=\"" . $dateString . "\\" . basename($_FILES["彩信文件"]["name"][$key]) . "\">" . basename($_FILES["彩信文件"]["name"][$key]) . "</a></p>\r\n"); } else { fwrite ($msglogTxt_handle, "<p>File attachment: <a href=\"" . $dateString . "\\" . basename($_FILES["彩信文件"]["name"][$key]) . "\">" . basename($_FILES["彩信文件"]["name"][$key]) . "</a></p>\r\n"); } } else { echo "Error uploading file ". basename( $_FILES["彩信文件"]["name"][$key]) . "<br/>"; } } } } fwrite ($msglogTxt_handle, "<!-- End message block -->\r\n"); /* If we saved previous message entries to msglog.tmp, we need to add them back to this file */ if (@file_exists ($msglogTmp)) { fwrite ($msglogTxt_handle, file_get_contents ($msglogTmp)); @unlink ($msglogTmp); } fclose ($msglogTxt_handle); } /* If we didn't save any images (message is text only), then delete the temporary directory */ if (!$savedImageFile && $image_path) { @rmdir ($user_path . $dateString); } } /* Now we put the HTML footers in place, creating index.html in the user directory */ if (!$errorFlag) { $htmlFile = $user_path . "index.html"; $htmlFile_handle = @fopen ($htmlFile, "w+"); if (!$htmlFile_handle) { if ($returnHttp500OnError) header("HTTP/1.0 500 Internal Error"); echo "ERROR: Cannot create file in user upload directory " . $user_path; $errorFlag = True; } else { fwrite ($htmlFile_handle, "<html>\r\n<head>\r\n<title>MMS Message Log for " . $_REQUEST['MMSFrom'] . "</title>\r\n</head>\r\n<body>\r\n"); fwrite ($htmlFile_handle, "<h1>MMS Message Log for " . $_REQUEST['MMSFrom'] . "</h1>\r\n"); fwrite ($htmlFile_handle, file_get_contents ($user_path . "msglog.txt")); fwrite ($htmlFile_handle, "</body>\r\n</html>\r\n"); fclose ($htmlFile_handle); } }

该脚本首先执行一些参数验证。

该脚本进行测试以确保“ MMSFrom”变量存在并且是非空白的,其中包括消息发送者的电话号码。如果此变量不存在或为空,则脚本返回错误。

该脚本进行测试以查看是否存在“ MMSSubject”变量。如果此变量不存在或为空,则使用默认主题“多媒体消息”。

该脚本会测试“ 彩信文件”数组,以确定是否有任何与请求相关联的上载文件。如果请求中不包含上载的文件,则返回错误。

如果该目录不存在,该脚本会为该用户创建一个目录。用户目录在$ upload_path变量指定的目录下创建。

该脚本验证其是否具有在用户目录中创建文件的能力。如果在创建用户目录或在用户目录中创建临时文件时出错,脚本将返回错误。

该脚本在用户目录下创建一个子目录,以包含与当前MMS消息关联的内容。为每条消息创建一个单独的子目录,因为随着时间的流逝,用户可能会发送具有相同名称的多个文件,并且在此示例中,我们既要保留新内容又要保留旧内容,同时还要保留原始文件名。为每个收到的MMS消息创建一个单独的目录是完成这些目标的一种简单方法。该脚本验证它可以创建此目录,并且可以在新创建的目录中创建临时文件。

该脚本在用户目录中维护两个文件:msglog.txt和index.html

index.html是一个HTML文件,其中包含以前所有接收到的MMS消息的日志,并已转换为HTML格式。邮件以最新到旧的顺序列出在此文件中。

msglog.txt包含所有先前收到的MMS消息的日志,类似于index.html。但是,此文件不包含完整的HTML,它仅包含转换后的消息,而没有所有必要的HTML标头。该脚本除了维护index.html之外,还维护该文件,以简化每次接收到新的MMS消息时重新生成index.html所需的处理。

脚本验证了输入参数后,它将创建名为msglog.tmp的msglog.txt文件的备份。

然后,它创建一个新的msglog.txt文件,循环遍历MMS消息的内容,并将MMS消息重新格式化为简单的HTML块。 HTML块以MMS消息的主题行作为标题开始,后跟日期/时间戳。然后,脚本循环遍历MMS消息的内容。作为MMS消息内容一部分的文本文件直接包含在HTML内容中。图像文件被包含为HTML内容中的直接图像参考。 SMIL文件将被跳过并丢弃。其他内容通过HTML内容内的链接包括在内。

完成MMS消息的处理后,该脚本会将先前备份的备份到msglog.tmp文件的消息追加到msglog.txt文件。然后,脚本将插入必要的HTML标头,以基于msglog.txt文件的内容创建index.html。

有关安装/配置PHP和测试PHP脚本的说明

使用mmsreceive.php脚本假定您已熟悉PHP。您可以在以下位置找到有关PHP的更多信息: http://www.php.net.

如果要在Windows平台上安装PHP,请在以下位置获取安装指南: http://www.iis-resources.com/modules/AMS/article.php?storyid=615 可能非常有用。该安装指南中唯一真正的缺陷是,当它向IIS注册“ .PHP”扩展名时,它假定PHP是Web服务器将提供的唯一动态内容类型。要使用IIS手动注册“ .PHP”扩展名,请在IIS管理器中右键单击“网站”,选择“属性”,转到“主目录”页面,按“配置”按钮,然后即可在此处注册“ .PHP”扩展名以使用“ php5isapi.dll”可执行文件。

设置PHP的另一个潜在麻烦是,需要配置Web服务器以允许您的脚本写入$ upload_path目录,您将在其中放置接收到的MMS消息内容。用户在PHP手册的部分中提供了注释,该注释记录了“处理HTTP文件上载”的文档,该文档当前可从以下位置在线访问: http://php.net/manual/en/features.file-upload.php,这在这方面很有帮助。本质上,您必须授予IIS用户帐户(IUSR_yourservername)对上载目录的读取,写入和目录浏览权限。

这些问题不在NowSMS的范围内。为了帮助您对脚本进行故障排除,建议您在开发和测试脚本时,而不是最初使用实时MMS内容对其进行测试,而是使用模拟MMS内容进行测试。可以部署一个简单的HTML Web表单来测试对您的PHP脚本执行HTTP File Upload Post。我们在ZIP文件下载中包含了一个简单的HTML Web表单示例(mmsreceive.html),其中包含本文档描述的PHP脚本(http://www.zgbianpofanghuwang.com/download/php2waymms.zip )。

该网络表单如下所示。如您所见,这是一种非常简单的形式,允许您输入MMSFrom和MMSSubject变量的值,以及最多12个上载的文件作为MMSFile []数组传递给脚本。

<html>

<head>

<title>File Upload Test for MMSReceive.php Script</title>

</head>

<body>

<form enctype="multipart/form-data" action="mmsreceive.php" method="POST">

<h1>File Upload Test for MMSReceive.php Script</h1>

<input type="hidden" name="MAX_FILE_SIZE" value="10000000" />

Sender Phone Number:  <input name="MMSFrom" type="text" /><br />

Message Subject:  <input name="MMSSubject" type="text" /><br />

Choose one or more files to upload:

<br/>

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input name="彩信文件 []" type="file" /><br />

<input type="submit" value="Upload File" />

</form>

</body>

</html>

配置NowSMS以调用您的PHP脚本

应该指出的是,我们最后保留了这一重要细节。做出此决定的原因很简单。在配置NowSMS连接到脚本之前,您应该彻底测试脚本。即使您仅使用本示例中提供的测试脚本,也应在配置NowSMS与其连接之前,使用示例Web表单对脚本进行测试。我们之所以建议这样做,是因为以这种方式更容易测试和调试脚本或PHP配置问题。当NowSMS生成传递实际MMS消息的自动帖子时,测试和调试问题更加困难。

配置NowSMS以连接到PHP脚本的第一步是在NowSMS配置对话框的“ MMSC路由”页面上定义到脚本的连接。按“添加”添加路由。

与PHP脚本的连接定义为来自的外部连接。 NowSMS MMSC,其定义类似于定义MM7连接的过程。

“帐户名称”和“帐户描述”参数可以包含任何值(仅使用字母和数字)。这些值仅用于标识NowSMS中与PHP脚本的连接。

“默认发件人地址”应留为空白,并应选中“允许发件人地址覆盖”。

在大多数配置中,“将邮件路由到此帐户以获取收件人的电话号码”应保留为空白。

“将消息路由到VASP的方式”应设置为MM7。

“服务器地址”应包含您的PHP脚本的网址(例如,http://server/mmsreceive.php)。

除非您的脚本或服务器要求用户验证,否则“登录名”和“密码”应保留为空白。如果这些参数不是空白,则NowSMS将使用它们来构建基本身份验证“ Authorization:”标头,以在连接到PHP脚本时使用。

“ VASP ID”,“ VAS ID”,“服务代码”,“使用反向计费”,“连接类型”,“ 3GPP MMS版本”,“ MM7架构”和“从MM7 XML删除空白”都可以保留在空白或默认值,因为对于这种类型的连接,它们将被忽略。

如果您使用的是示例脚本,则“ Max Connections”应保留为空白或设置为1。 (如果示例脚本同时运行多次,则可能会感到困惑。)

“非标准MM7变体”应设置为“ PHP分段文件上传”。

上面的定义仅告诉NowSMS它如何连接到您的PHP脚本。但是,它没有将NowSMS配置为实际调用PHP脚本来处理收到的MMS消息。完成此过程将根据您接收MMS消息的方式而有所不同。有三种不同的配置替代方案:

  1. MMS消息是通过GSM / GPRS调制解调器接收的。在此配置中,NowSMS的“ SMSC”列表中的GSM / GRPS调制解调器定义的“属性”下有一个“ MMS设置”选项。 “ MMS设置”对话框包含一个名为“接收消息的MMSC路由”的选项,该选项应设置为“路由到MM7”,并选择分配给您的PHP脚本的名称(来自上一章中“ MMSC路由”的定义)步)。
  2. 使用支持的协议之一(包括MM7,MM4或EAIF),通过直接连接到运营商MMSC的方式接收MMS消息。当使用这些协议中的任何一个时,操作员MMSC将自动连接到您的 现在短信& 彩信Gateway 传递消息。为NowSMS安装中的移动运营商连接定义了“ MMSC VASP”帐户。 “ MMSC VASP”定义包括一个名为““ MMSC路由接收消息””的选项,该选项应设置为“路由到MM7”,并选择分配给您的PHP脚本的名称(来自上一章中“ MMSC路由”定义)步)。
  3. NowSMS是MMSC。在这种情况下,您可以使用“ MMSC路由”定义中的“将消息路由到此帐户以获取收件人的电话号码”选项,以根据收件人的电话号码将消息路由到您的PHP脚本。 (例如,在此字段中定义1234,并且如果您的任何MMSC用户将MMS消息发送到1234,它将被路由到您的PHP脚本。)

有关运营商MMSC连接和GSM / GPRS调制解调器的更多信息,请参阅标题为“ 连接到运营商MMSC.