网站开发日志

2009年11月9日星期一

网页同时含有安全性与非安全性的项目

当网页内包含HTTP及HTTPS的内容时,在IE下会出现弹出 "…网页同时含有安全性与非安全性的项目…"的警告讯息;在Firefox下,你将看到有下角的安全锁图标裂开了。这通常不是什么大问题。

如何你在浏览别人的网站,

  1. 在IE下你可以通过:
    工具->选项->安全性->自订等级将『显示混合的内容』由"提示"修改为"启用"即可。
  2. 在Forefox下,你可以忽略那个裂开的安全锁。

如果你拥有这个网站,那么你应该考虑避免在安全页面包含非安全的元素,也就是在https页面里,把http://打头的href用https://或者相对路径代替。当然,前提是该元素可以通过https接入。

https是需要购买安全证书的,不是什么网站随随便便在前面加上https就可以访问,例如:https://www.61dh.com是不可以访问的,因为我没有买安全证书。另外SSL安全证书是和域名对应的,比如说我买了https://secure.61dh.com,它只对sercure.61dh.com生效,而https://www.61dh.com依然无法访问。

如果一个安全页面上含有非安全元素(通常是链接或者图片),并且这些链接不支持安全连接。那么应该怎么办呢?

这里要介绍两个可行解决方案。(注意:下面用到https://secure.61dh.com只是用来举例说明的,它并不存在。)

方法一:在服务器配置文件里加入安全到非安全的跳转

在Apache服务器下,当访问https://安全页面时通常要先到达ssl.conf,而访问不安全页面通常先到达http.conf。所以我们可以在ssl.conf里对某些url进行跳转。这种方法是用于同域名跳转,例如:

RewriteCond   %{REQUEST_URI}  !^/cart/checkout/.*$
RewriteRule   ^/(.*)$         http://%{HTTP_HOST}/$1  [R,L]

上述Rewrite Rule,可以实现 https://secure.61dh.com/cart/http://www.61dh.com/cart 的跳转。

方法二:使用PHP跳转代码

当安全页面含有外部链接时,这个方法很适用。例如在https://secure.61dh.com页面里含有http://www.cpzhan.com的友情链接,我们可以把这个链接用安全链接来表示:

<a href="https://secure.61dh.com/redirect.php?to=http%3a%2f%2fwww.cpzhan.com">
彩票站</a>

注意:这里我用到redirect.php,这个文件支持安全链接,而非安全链接http://www.cpzhan.com被当成变量。redirect.php代码很简单,如下:

<?php
$to    = isset($_GET['to'])      ?  $_GET['to']       : '';
if ($to){
   header("Location: $to") ;
   exit;
}
?>

标签: ,

2009年10月12日星期一

密码加密

我经常在数据库的表里或者在代码里看到未经加密的密码,这是一个很不好的习惯。PHP里提供很多种的密码加密函数,在正式的项目开发里,我们应该要重视密码的加密。

我们可以在用户注册帐号的时候,使用md5()或者sha1()加密用户输入的密码,然后保存在数据库里。下次用户登入的时候,把用户输入的密码通过md5()或者sha1()函数计算出加密值,然后用这个加密值和数据库里的保存密码进行比较,如果相等就代表密码正确,反之亦然。

实例代码如下:

<?hpp
$pass=$_POST['pass']; 
$save = md5($pass); //保存这个加密过的密码
if(strcmp(md5($pass),$save)==0)
  echo"密码正确";
else
  echo"密码不对";
?>

注意使用md5或者sha1()加密过后的值是不可以逆的,也就是说通过这个加密值你无法还原原始值。所以如果你忘记密码,你只有重新设置密码。

有时候,你可能需要一个可以还原的加密方法。这时使用上面的加密函数就行不通了,但是你完全可以自己写一个,这里就要介绍一个用base64_encode()和base64_decode()来创建自定义密码加密的方法。

首先,创建下来LIB文件,命名为pass.php, 保存在你的库文件目录下。

<?php
function myencode($str)
{
  for($i=0; $i<5;$i++)
  {
    $str=strrev(base64_encode($str));
  }
  return $str;
}
function mydecode($str){
  for($i=0; $i<5;$i++)
  {
    $str=base64_decode(strrev($str)); 
  }
  return $str;
}
?>

然后,用下面的代码创建一个加密后的密码:

<?php 
include ("LIB/pass.php");
echo myencode($argv[1]);
?>

把上面代码命名为mypass.php, 然后在命令行运行:

php mypass.php 61dh
VZlSXRVVONXTWl1daZkVaNGbKVVVB1TP

最后,在实际代码里,使用这个来代替加密过的代码来代替真实密码。

<?php
include ("LIB/pass.php");
$pass = 'VZlSXRVVONXTWl1daZkVaNGbKVVVB1TP';
$real_pass = mydeocde($pass);
?>

当然,这种方法只是在一定程度上保护了密码,如果别人可以介入你的库文件(pass.php),加密的字符串将马上就可以被还原。但是这总是比让人一目了然就看到你的密码来的好。

标签:

2009年8月11日星期二

PHP实用代码系列 - 计算页面加载时间

网页的加载时间很重要,没有人喜欢花好几分钟来等待一个页面加载完毕。影响页面加载速度的因素很多,对于动态网页,其中一个重要因素是代码的效率。不论用那种语言来写网站的人,我们都应该重视代码的效率,注重效率也是优秀程序员和新手的一个重要区别。当你给你的页面加入一些代码的后,最后要检测一下新加入的代码有没有给页面的加载造成很大的影响。下面是一个适用的PHP代码,它可以用来计算页面的加载时间 (更新: 8/12/2009)。

<!-- 把这段反正页面顶部 -->
<?php
   $mtime = explode(" ",microtime());
   $starttime = $mtime[1] + $mtime[0];
?>
 
<!-- 把实际代码放在下面 -->
 
 
<!-- 把这段代码放在页面底部-->
<?php
   $mtime = explode(" ",microtime());
   $endtime = $mtime[1] + $mtime[0];
   $totaltime = ($endtime - $starttime);
   echo "页面加载时间为: ".$totaltime."";
?>

更新:

谢谢扑街囝的回复。我想你指的是

<?php
$start_t = time() + microtime();
//do sth.
$end_t = time() + microtime();
$timer = $end_t - $start_t;
echo $timer;
?>

这确实要精简。其实在PHP5里有更加精简的写法:

<?php
$start_t = microtime(true); //加入true,microtime输出为浮点值
//do sth.
$end_t = microtime(true);
$totaltime = $end_t - $start_t;
echo "页面加载时间为: ".$totaltime."";
?>

标签: ,

2009年8月8日星期六

Amazon S3

Amazon S3 is an online storage web service offered by Amazon Web Services. My company have being used to host some images for a while, and it works great, fast and cheap.

Recently, I found a handy tool called s3up, which lets you

upload files using custom headers so they’re served back with a proper expiration date and gzipped when possible — i.e., the techniques recommended by YSlow.

And I have used it to upoad some Javascripts to be hosted on Amazon S3, which largely reduces my company server's bandwidth usage. But there is small issue when you use this command line tool in old version of PHP (<5.2). PHP has a function to return information about a file, but this function does not return PATHINFO_FILENAME constant until PHP 5.2.0. So, you have to tweak the code little bit, for example, I added a custom function (Credit: Lostindream at atlas dot cz) below to get FILENAME constant for PHP < 5.2.0.

function path_info($filePath){
   $fileParts = pathinfo($filePath);
   if(!isset($fileParts['filename'])){
    $fileParts['filename'] = substr($fileParts['basename'], 0, strrpos($fileParts['basename'], '.'));
   }
   return $fileParts;
}
So the revised version is here. The usage can be found from original post.  I doubt people is using Amazon S3 in China, so this post is in English. If you are interested in Amazon S3 and have any related questions, please leave your message.

标签:

2009年8月2日星期日

NetBean IDE for PHP

在公司写PHP代码我一般都是在Linux下用VIM, 而在家里我用的是UltraEdit。这几天才发现UltraEdit在保持PHP文件时为UTF8时会加入BOM (byte-order mark), 一般情况下这不造成什么问题,因为浏览器解析代码的时候,会识别这个特殊标识而忽略它。但是有时候它会给你带来莫名其妙的问题,就像我在Wordpress 搬家记录一文里提到的header already sent的问题,不过你可以在保存UTF-8是选择NO-BOM来解决问题。

我一直没有用IDE,突然间觉得应该学着用用,市面上这么多IDE,他们的存在总是有他们的理由,所以今天下载了NetBean IDE for PHP,决定用他来开发cpzhan项目,另外NetBean还支持FTP功能,修改代码后直接就可以上传到服务器了。虽然UltraEdit也有FTP功能,但是NetBean在项目管理,PHP语法检查方面要比UltraEidt强悍多了。

我相信NetBean的很多功能还等待我去学习,几个小时的试用最让我开心的时,NetBean帮我找到了困扰我好几天的json问题的原因。我用NetBean打开getTerm.php (这个代码用来生产一组json格式的数据), 发现在<?php前多了一个点,我想这就是所谓的BOM。多了这一点(BOM),getTerm.php运行没什么问题(可能会有warning), 用浏览器打开,照样收到json字符串,但是这个json字符串已经不是正确合法的格式了,因为这个字符前有一个用看不见的标识在那里,导致json_decode无法还原json编码前的数组。最终把这个多余的点删除后,解决了问题!!!

注意:用jQuery的getJSON它会忽略这个特殊字符,这就是为什么在json问题里我用getJSON可以的原因。

标签:

2009年7月26日星期日

json问题

今天在给我的cpzhan.com写一个很小的API,主要是在服务器端提供一组数据,如果按照往常我会使用XML,但是最近在学习json,所以就json来试试。按照我上篇日志的介绍,代码如下:

<?php
require("../lib/config.inc.php");
require("../lib/Database.class.php");
$db = new Database($config['server'], $config['user'], $config['pass'], $config['database'], $config['tablePrefix']);
// connect to the server
$db->connect();  
$sql = "SELECT * FROM results ORDER BY UID DESC LIMIT 1";  
$row = $db->query_first($sql);
$current_year = date('Y');
$year = $row['Year'];
$row['Next_Term'] = ($current_year == $year) ? ($row['Term'] + 1) : 1;
$row['Next_Year'] = $current_year;
$row['Next_DRAW_DATE'] = date('Y-m-d');
//上面的代码产生一组数组,然后用json_encode($row)产生json格式的字符串
echo json_encode($row);
?>

接下来,我在本地又写了一段代码,准备用来掉用上面写好的api,然后用json_decode, 把数组还原。

<?php
$url = 'http://www.cpzhan.com/api/getTerm.php';
$jsonfeed = file_get_contents($url);
echo $jsonfeed;
//这里我收到到了json格式的字符串
$result = json_decode($jsonfeed, true);
print_r ($result);
//!!!但是这里无法还原编码前的数组
?>

不知道什么原因,json_decode无法还原编码前的数组。很明显,我上面写的api输出的字符串无法被json_decode识别,但是API的输出看上去的确是合法的json格式。我还试着给api的输出加上header如下, 終于找到原因了, 見netbean-ide一文的介绍)

<?php
ini_set('display_errors', 0);
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); 
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" ); 
header("Cache-Control: no-cache, must-revalidate" ); 
header("Pragma: no-cache" );
header("Content-type: application/json; charset=utf-8");
.....

但是还是没有起任何作用。最后我放弃了这种方法,改用我曾经介绍过的jQuery获取JSON数据的方法:

<script>
   $.getJSON("http://www.cpzhan.com/api/getTerm.php?callback=?",
   function(data){//data这里是JSON对象,它可以是由多个JSON对象组成
      $("#year").val(data.Next_Year);
      $("#term").val(data.Next_Term);
      $("#date").val(data.Next_DRAW_DATE);
   });
</script>

一开始,我收到错误信息:invalid label,上网搜索了一下终于找到了原因,原来jQuery在调用getJSON的时候会在callback后自动加上值,因此我的产生JSON数据的时候要加上callback, 并且要用大括号把encode后的JSON数据包裹。如下:

<?php
ini_set('display_errors', 0);
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); 
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" ); 
header("Cache-Control: no-cache, must-revalidate" ); 
header("Pragma: no-cache" );
header("Content-type: application/json; charset=utf-8");
//$row是要传递的数组
$jsonp = $_GET['callback']; //callback的是jquery自动加入的
$myJSON = json_encode($row);
echo $jsonp. '(' . $myJSON . ')'; //注意:json_encode的结果被大括号包裹

至于为什么要这么做我还没有搞懂(可能是出于安全的考虑),但是我想这很可能是我上面用PHP获取JSON数据失败的原因,我们必须对API的输出做特殊处理后,json_decode才可以识别。如果有朋友对JSON精通,请留言告知。谢谢!

标签: ,

2009年7月22日星期三

PHP和json简介

我在日志里曾经介绍过如何使用jQuery解析JSON格式的feed。今天准备简单介绍如何使用PHP输出JSON格式的Feed以及如何使用PHP解析JSON格式的Feed。JSON是一种轻便的数据交换格式,和XML的用途显示,但是相比之下XML要臃肿许多。至于XML和JSON那个更有优势,我也说不上,但是听说JSON的处理速度要比XML快,似乎挺有道理。JSON是全称是Javascript Object Notation(Javascript对象标记法),它的结构不如XML直观,特别对初学者来说,下面就是一个最基本、最简单的JSON feed的例子,你可以看到一个对象是有一组无序的对数组成,并用大括号括起来;而对数十用逗号分隔;而对数的名称和值用冒号分隔。

{name:adam,date:2009-07-22,title:PHP and JSON}
//最基本的JSON Feed

通常JSON Feed的结构往往不是这么简单,因为他的值得类型很多,可以是string、number、object、array、true、false、null等等,如果你的值里含有控制符号(大括号,冒号,中括号等等),你还要使用转义符。在这里我不准备做详细介绍,你可以参考http://json.org

PHP5.2后PHP自带有JSON的encoder和decoder,PHP5.2以前的版本你可以使用ZEND的JSON库。

使用PHP的JSON encoder,你可以把相关数组转换成JSON格式,下面是一个例子:

<?php
 $today = date("D M j G:i:s T Y");
 $status = array(
     "text" => "大家好!".
         "最近一直都很忙,但是我会尽量经常更新我的日志;" .
         "把学到的东西记录下来、分享给大家",
     "created_at" => "$today"
 );
 $name = array("name" => "adam");
 $status['user'] = $name;
 $myJSONstatus = json_encode($status);
 echo $myJSONstatus;
 ?>
//输出结果:
{"text":"\u5927\u5bb6\u597d\uff01\u6700\u8fd1\u4e00\u76f4\u90fd\u5f88\u5fd9\uff0c\u4f46\u662f\u6211\u4f1a\u5c3d\u91cf\u7ecf\u5e38\u66f4\u65b0\u6211\u7684\u65e5\u5fd7;\u628a\u5b66\u5230\u7684\u4e1c\u897f\u8bb0\u5f55\u4e0b\u6765\u3001\u5206\u4eab\u7ed9\u5927\u5bb6","created_at":"Wed Jul 22 22:33:44 EDT 2009","user":{"name":"adam"}}

注意:以上的输出里有很多4位的十六进制代码,这是因为json_encode把中文都转换为对应的十六进制代码。

和encoder对应,我们还可以使用json decoder把JSON feed转换成object或者array。例如:

<?php
$url = 'http://feeds.delicious.com/v2/json/tags/61dh?count=100';
$jsonfeed = file_get_contents($url);
echo $jsonfeed;
$result = json_decode($jsonfeed, true); 
//把第二个变量是控制输出类型的,true为Array,默认(false)为Object
print_r ($result);
?>
输出结果:
Array
(
    [ajax] => 8
    [CSS] => 19
    [HTML] => 16
    [Javascript] => 37
    [jQuery] => 37
    [jQuery基础] => 11
    [Linux] => 5
    [mySQL] => 3
    [Perl] => 5
    [PHP] => 25
    [PHP实用代码系列] => 4
    [Smarty] => 2
    [博客] => 21
    [浏览器] => 10
    [百度知道] => 4
    [素材] => 2
    [编程开发] => 7
)

http://feeds.delicious.com/v2/json/tags/61dh?count=10 这个链接是美味书签提供的,经常光临我的日志的朋友,可能知道,我没发布一篇文章都会把链接加到美味书签,然后使用它产生本站的日志分类。使用json-decode, 我就可以从json feed里把日志分类和文章数解析出来。

如果你用的5.2以前的版本,你可以使用Zend的Json库,一般PHP服务器带有Zend。使用方法如下:

<?php
require_once 'Zend/Json.php';
//encode例子:
$today = date("D M j G:i:s T Y");
 $status = array(
     "text" => "大家好!".
         "最近一直都很忙,但是我会尽量经常更新我的日志;" .
         "把学到的东西记录下来、分享给大家",
     "created_at" => "$today"
 );
 $name = array("name" => "adam");
 $status['user'] = $name;
echo Zend_Json::encode($status);
//decode例子:
$url = 'http://feeds.delicious.com/v2/json/tags/61dh?count=100';
$jsonfeed = file_get_contents($url);
echo  Zend_Json::decode($jsonfeed);
?>

标签:

2009年7月20日星期一

reCAPTCHA - 帮你帮我

CAPTCHA 是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机和人的公共全自动程序。CAPTCHA目前广泛用于网站的留言板,许多留言板为防止有人利用计算机程式大量在留言板上张贴广告或其他垃圾讯息,因此会放置CAPTCHA要求留言者必需输入图片上所显示的文数字或是算术题才可完成留言。

虽然自己动手写一个简单的CAPTCHA程序也不是很难,但是这里要介绍的如何使用reCATPCHA。reCAPTCHA计划的主要目的是利用CAPTCHA技术来帮助典籍数字化的进行,这个计划将由书本扫描下来无法准确的被光学文字辨识技术识别的文字显示在CAPTCHA 问题中,让人类在回答CAPTCHA问题时用人脑加以识别。为了验证人类所输入的文字是正确的,而不是随意输入,每次有两个字会被显示出来;一个是光学文字辨识软件无法辨别的字,另一个是一个已经知道正确答案的字。如果使用者正确的回答出已知正确答案的字,那么就假设所输入的另一个光学辨识软件无法辨识的字是认真的检视后被输入而非随便输入。因此,每一次有效的验证也是对reCAPTCHA计划的贡献。

(以上文字大部分摘自wiki

要把reCAPTCHA加到你的网站里很简单,reCAPTCHA提供适合于多种程序语言的接口,这里要介绍的reCAPTCHA PHP库的运用。

  • 首先到reCAPTCHA网站上获取API Key,这需要注册,但是是完全免费的。
  • 然后下载reCAPTCHA PHP库
  • 最后调用库函数。下面提供示例,通常这些代码是加在表单(form)里,你需要根据实际情况修改,如有问题请留言。
<?php
require_once('recaptchalib.php');
$publickey = "注册后你将得到这个key"; 
$privatekey = "注册后你将得到这个key";
# the response from reCAPTCHA
$resp = null;
# the error code from reCAPTCHA, if any
$error = null;
$switch = 0;
# are we submitting the page?
if ($_POST["submit"]) {
  $resp = recaptcha_check_answer ($privatekey,
                                  $_SERVER["REMOTE_ADDR"],
                                  $_POST["recaptcha_challenge_field"],
                                  $_POST["recaptcha_response_field"]);
  if ($resp->is_valid) {
	$switch = 1;	
  } else {
  	$switch = 2;
    $error = $resp->error;
  }
}
?>
<form name="validation" enctype="multipart/form-data" action="" method="post">
<!--下面的javascript变量可以控制图片的主题外观,当然这是可选的-->
<script>
var RecaptchaOptions = {
   theme : 'clean',
   tabindex : 2
};
</script>
<?php
if ($switch == 0){
	echo '有空?给reCAPTCHA项目贡献几个字吧:-)';
//你可以把表单内容放在这里
}
elseif ($switch == 2){
	echo '你是机器人?不是的话,请再输一次。';
}
else{
	echo '谢谢你对reCAPTCHA的支持';
//这里加入表单提交成功后的提示信息
}
//下面是重要的recaptcha函数,调用captcha的图片
echo recaptcha_get_html($publickey, $error); 
?>
//这里可以加入其他表单信息
<input type="submit" name="submit" value="submit" />
</form>

下面我用iframe把reCAPTCHA加入这个帖子里,这个表单不传递其它信息,仅供网友测试,同时给reCAPTCHA做点贡献。:-)

reCAPTCHA - 一个帮你帮我的项目,不是吗?

标签: ,

2009年6月22日星期一

PHP发送Gmail邮件加附件

前一段,我介绍了如何用PHP调用Gmail发送邮件,此方法只适用于发送文本邮件,也就是不支持附件发送。其实,要发送附件也不难,只是需要安装一个模块:Mail-Mime。下面就给大家做过详细介绍。

1.首先安装Mail-Mime, 你可以到pear网站下载后安装,如果你的机子装有Pear的包管理器,你直接运行下面的命令即可:

mail-mime pear install -o Mail_Mime
#在unbuntu下,使用sudo
sudo mail-mime pear install -o Mail_Mime

2. 使用下面的代码,这和PHP调用Gmail发送邮件一文中介绍的代码相识,不同的是多了Mail_Mime, 它是用来构造邮件的主题部分(内容和附件):

<?php
require_once "Mail.php";
require_once "Mail/mime.php";
//请用你的Gmail帐号和密码替代
$host = "smtp.gmail.com";
$username = "your-account";
$password = "your-password";
//定义收信人,发信人,以及主题和信息等
$from = "Adam<your@gmail.com>";
$to = "Cindy<someone@any.com>";
$subject = "Hi!";
$text = "Hi,\n\nHow are you?";
$html = "<b>hi</b>; 你也可以发送HTML格式的邮件
//定义附件路径和名称
$file = "/root/test/mail.php";
//如果你对下面的代码不熟悉,那么就请保留原样
$crlf="\n";
$headers = array (
	'From' => $from,
  	'Subject' => $subject);
$mime = new Mail_mime($crlf);
$mime->setTXTBody($text);
$mime->setHTMLBody($html); //发送HTML
$mime->addAttachment($file, 'text/plain');
$body = $mime->get();
$hdrs = $mime->headers($headers);
$smtp = Mail::factory('smtp',
  array ('host' => $host,
    'auth' => true,
    'username' => $username,
    'password' => $password));
$mail = $smtp->send($to, $hdrs, $body);
if (PEAR::isError($mail)) {
  echo("<p>" . $mail->getMessage() . "</p>");
 } else {
  echo("<p>Message successfully sent!</p>");
 }
?>

注意:在上述代码里,我使用的附件内容类型是文本(content-type:text/plain)。如果你要发送PDF,图片,ZIP等其他文件类型,你可以使用下面的代码代替:

$mime->addAttachment($file, 'text/plain'); //文本
$mime->addAttachment($file, 'application/pdf'); //PDF
$mime->addAttachment($file, 'image/gif'); //图片
$mime->addAttachment($file, 'application/zip'); //ZIP
关于content_type (内容类型),请参考:w3schools的介绍

标签:

2009年6月17日星期三

PHP中的值是否为空

在百度知道看到一个网页提问,是关于PHP中的值是否为空。这个问题还是相对简单,参考PHP手册,以下几种情况在PHP里被定义为空:

  • "" (an empty string)
  • 0 (0 as an integer)
  • "0" (0 as a string)
  • NULL
  • FALSE
  • array() (an empty array)
  • var $var; (a variable declared, but without a value in a class)

掌握这些规则,我们就可以对下面的PHP变量进行是否为空的判断。

<?php
$a1 = null;
$a2 = false;
$a3 = 0;
$a4 = '';
$a5 = '0';
$a6 = 'null';
$a7 = array();
$a8 = array(array());
echo empty($a1) ? 'true' : 'false';  //true
echo "<br>";
echo empty($a2) ? 'true' : 'false';  //true
echo "<br>";
echo empty($a3) ? 'true' : 'false';  //true
echo "<br>";
echo empty($a4) ? 'true' : 'false';  //true
echo "<br>";
echo empty($a5) ? 'true' : 'false';  //true
echo "<br>";
echo empty($a6) ? 'true' : 'false';  //false, 因为$a6不是空字符串也不是'0'
echo "<br>";
echo empty($a7) ? 'true' : 'false';  //true
echo "<br>";
echo empty($a8) ? 'true' : 'false';  //false,因为$a不是空数组
?>

标签: ,

2009年6月2日星期二

PHP调用Gmail发送邮件

大家对PHP的mail()函数一定都很熟悉,它简单易用,这里就不介绍了。如果你不知道怎么用,请查看PHP的在线手册。但是mail()并不是在任何服务器上都可以用的。下面是两个使用mail()的主要先决条件:

  • 1.服务器必须安装有sendmail
  • 2.smtp服务器无需鉴权(authentication)

比如自家的服务器,我在'Ubuntu命令行发送邮件到远端'一文里介绍过这个问题。 今天我准备介绍另外一种方法: PEAR:Mail + Gmail。首先,安装PEAR Mail, 这需要3个模块:NET/SMTP, Mail,Net/Socket。

如果你用的是RedHat,具体步骤如下:

1. 下载文件:
# cd /tmp
# wget http://download.pear.php.net/package/Mail-1.1.14.tgz
# wget http://download.pear.php.net/package/Net_SMTP-1.2.10.tgz
# wget http://download.pear.php.net/package/Net_Socket-1.0.8.tgz
2. untar 所有文件:
# tar -zxvf Mail-1.1.14.tgz
# tar -zxvf Net_SMTP-1.2.10.tgz
# tar -zxvf Net_Socket-1.0.8.tgz
3.安装文件:
# cd /usr/share/pear
# mkdir Net
# cd Net
# cp /tmp/Net_SMTP-1.2.10/SMTP.php .
# cp /tmp/Net_Socket-1.0.8/Socket.php .
# cd ..
# cp -avr /tmp/Mail-1.1.14/Mail/ .
# cp -avr /tmp/Mail-1.1.14/Mail.php .

如果你用的是Ubuntu,相对要简单一些:

1.如何你还没有装PEAR:
sudo apt-get install php-pear
2.有了pear以后,直接使用下面的命令:(提示:使用 ‘--alldeps’ 可以自动安装Mail的相关模块)
sudo pear install --alldeps Mail

安装好Pear的Mail模块后,你就可以使用PHP代码调用Gmail来发送邮件了。下面的代码可供参考:

<?php
require_once "Mail.php";
 
$from = "Adam <adam@gmail.com>";
$to = "Cindy <cindy@61dh.com>";
$subject = "Hi!"; //邮件主题
$body = "Hi,\n\nHow are you?"; //邮件内容
 
$host = "smtp.gmail.com";
$username = "adam"; //gmail用户名
$password = "mima-pass"; //gmail密码
 
$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>");
}
?>

参考资料:

https://help.ubuntu.com/community/PhpPear
http://www.cyberciti.biz/tips/howto-php-send-email-via-smtp-authentication.html

标签: ,