http://backend;和http://backend/;有什么区别呢?

location /service/ {
proxy_pass http://backend;
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
}

location /service/ {
proxy_pass http://backend/;
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
}
同样访问:http://neverstay.com/service/add.php
前者配置,在后端的机器,收到的是http://neverstay.com/service/add.php
后者配置,在后端的机器,收到的是http://neverstay.com/add.php

如果换成下面这样,会报错:
location ~ ^/(service)/ {
proxy_pass http://backend/;
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
}
"proxy_pass" may not have URI part in location given by regular expression, or inside named location, or inside the "if" statement, or inside the "limit_except" block in nginx.conf:

但是,这样就没问题了:
location ~ ^/(service)/ {
proxy_pass http://backend;
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
}
把proxy_pass末尾的斜线去掉,就可以了,估计前段时间遇到的后端双层目录也跟这个有关,具体原因待查。。。

posted @ 2011-10-27 10:59 xin478 阅读(227) 评论(0) 编辑

前不久我写过的一篇关于用socket发送邮件的随笔---在php中使用SMTP通过密抄批量发送邮件,算是对那几天工作的小结。但是,通过这几天的使用,的确发现了一些问题。

首先,如果没有记错的话,以前我有提到我们公司的服务器是放在美国的,跑的是linux。但是,我在本地测试的时候,为了图个速度快,实际上,测试各项功能时,我使用了126的邮箱进行发送的。实际上,马上就证实了这个是我的疏忽。投入使用后,突然发现问题大条了。原来使用密抄的目的,是为了让各收件人间无法知道邮件还发给了谁,但是通过那台服务器发送的邮件,密抄地址居然全部列在上面,以至于有个收件的客户回了一封信给我们“Please send emails to mass recipients as bc (blind copy) so everyone doesn't have all email addresses.”

 

但是,我们的确是使用了密抄的啊,不能啊。但是,我在服务器上发给了自己,的确如此。

 

========================我是证据==============================

查看收到的邮件的头信息,也包含了本不应存在的bcc信息

 

可以我在本地测试,结果还是可以。那就神奇了,一样的代码,但是结果不一样。试了好几次,发现只要是使用qq、126之类的服务器来发送邮件,就不会显示。于是,就考虑是不是由于服务器上邮件发送程序不一样引起的或者是我的构造的信件格式有问题。于是,我用foxmail发送了一封到美国的服务器,结果他可以。看来是我的标头不规范了,qq、126能识别,美国佬的不行。

 

那知道了就改吧。通过抓包软件,可以得到一份完整的通讯记录,如下:

220 126.com Anti-spam GT for Coremail System (126com[20101010])

EHLO xin478-PC

250-mail
250-PIPELINING
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UrGJqy-UCa0xDrUUUUj250 8BITMIME


AUTH LOGIN

334 xxxxxxx

eGHuNDc7

334 xxxxxxxxxx


ODU1NzE2

235 Authentication successful

MAIL FROM: <xxxxxx@126.com>

250 Mail OK

RCPT TO: <noreply@xxxxx.com>

250 Mail OK


RCPT TO: <44522303@qq.com>

250 Mail OK

RCPT TO: <noreply@yoberryks.com>

250 Mail OK

RCPT TO: <44522303@qq.com>

250 Mail OK


Data

354 End data with <CR><LF>.<CR><LF>


Date: Mon, 25 Oct 2010 16:32:49 +0800
From: "xin478" <xin478@126.com>
To: "noreply" <noreply@xxxxx.com>
Cc: "44522303" <44522303@qq.com>
Subject: this is topic
Message-ID: <201010251632482022640@126.com>
X-mailer: Foxmail 6, 15, 201, 22 [cn]
Mime-Version: 1.0
Content-Type: multipart/alternative;
          boundary="=====003_Dragon220658716328_====="


This is a multi-part message in MIME format.

 

--=====003_Dragon220658716328_=====
Content-Type: text/plain;
charset="gb2312"
Content-Transfer-Encoding: 7bit

this is content

--=====003_Dragon220658716328_=====
Content-Type: text/html;
charset="gb2312"
Content-Transfer-Encoding: base64

PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv
L0VOIj4NCjxIVE1MPjxIRUFEPg0KPFNUWUxFIHR5cGU9dGV4dC9jc3M+QGltcG9ydCB1cmwoIEU6
XFRlbXBcSW50ZXJuZXQgwdnKsc7EvP5cc2Nyb2xsYmFyLmNzcyApOw0KPC9TVFlMRT4NCg0KPFNU
WUxFIHR5cGU9dGV4dC9jc3M+QGltcG9ydCB1cmwoIEU6XFRlbXBcSW50ZXJuZXQgwdnKsc7EvP5c
c2Nyb2xsYmFyLmNzcyApOw0KPC9TVFlMRT4NCg0KPFNUWUxFIHR5cGU9dGV4dC9jc3M+QGltcG9y
dCB1cmwoIEU6XFRlbXBcSW50ZXJuZXQgwdnKsc7EvP5cc2Nyb2xsYmFyLmNzcyApOw0KPC9TVFlM
RT4NCg0KPFNUWUxFIHR5cGU9dGV4dC9jc3M+QGltcG9ydCB1cmwoIEU6XFRlbXBcSW50ZXJuZXQg
wdnKsc7EvP5cc2Nyb2xsYmFyLmNzcyApOw0KPC9TVFlMRT4NCg0KPFNUWUxFIHR5cGU9dGV4dC9j
c3M+QGltcG9ydCB1cmwoIEU6XFRlbXBcSW50ZXJuZXQgwdnKsc7EvP5cc2Nyb2xsYmFyLmNzcyAp
Ow0KPC9TVFlMRT4NCg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PUdCMjMxMiIg
aHR0cC1lcXVpdj1Db250ZW50LVR5cGU+DQo8TUVUQSBuYW1lPUdFTkVSQVRPUiBjb250ZW50PSJN
U0hUTUwgOS4wMC43OTMwLjE2NDA2Ij48TElOSyByZWw9c3R5bGVzaGVldCANCmhyZWY9IkJMT0NL
UVVPVEV7bWFyZ2luLVRvcDogMHB4OyBtYXJnaW4tQm90dG9tOiAwcHg7IG1hcmdpbi1MZWZ0OiAy
ZW19Ij48L0hFQUQ+DQo8Qk9EWSBzdHlsZT0iTUFSR0lOOiAxMHB4OyBGT05ULUZBTUlMWTogdmVy
ZGFuYTsgRk9OVC1TSVpFOiAxMHB0Ij4NCjxESVY+PEZPTlQgc2l6ZT
0yIGZhY2U9VmVyZGFuYT50
aGlzIGlzIGNvbnRlbnQ8L0ZPTlQ+PC9ESVY+PC9CT0RZPjwvSFRNTD4NCg==

--=====003_Dragon220658716328_=====--


.

250 Mail OK queued as smtp1,C8mowKDLuQOxQMVMWetQAA--.41003S2 1287995571


QUIT

221 Bye

 

于是,大体是就明了了,基本上流程是这样的

一、建立TCP连接。
二、客户端发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令服务器端正希望以OK作为响应,表明准备接收。
三、客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行
四、协商结束,发送邮件,用命令DATA发送
五、以.表示结束输入内容一起发送出去
六、用QUIT命令退出结束此次发送。

 

而对于SMTP的命令而言,大抵用到的有这几种

  • HELO   向服务器标识用户身份
  • MAIL   初始化邮件传输mail from: <xxx>
  • RCPT   标识单个的邮件接收人;常在MAIL命令后面可有多个rcpt to: <xxx>
  • DATA   在单个或多个RCPT命令后,表示所有的邮件接收人已标识,初始化数据传输,以.结束
  • NOOP   无操作,服务器应响应OK
  • RSET   重置会话,当前传输被取消
  • QUIT   结束会话

我们可以观察到,在整个通讯的过程中,标头中并没有出现BCC的关键字,只是把邮件接收者都用RCPT TO按顺序都送出去了,我一直以为这个BCC是要的,而且为了区别,这封邮件我也抄送了一份(注意是抄送而不是密送),这个抄送的地址赫然在目 Cc: "44522303" <44522303@qq.com>

所以,我推测这个BCC是不用写的,不在To里面的和不在CC里面的,就是BCC,于是,我去掉了代码里输出BCC到标头这个行,重新发送了一次,的确,就可以了,不会显示密抄名单了。

 

但是,随即又发现一个新的问题,就是在收件人那栏里,使用密抄的话,不会显示当前收件人,而是会显示用MAIL TO 送出去的那个地址。在规范里,MAIL TO,CC,BCC三者只要有其中一个就可以了,于是,我又去掉了原来TO,这下,再发的时候,就看不到错误的收件人了。

 

这封是密抄给noreply@xx.com的邮件,但是在noreplay的账户里区看到了收件人为xin478@126.com

修改后,这个收件人就不会显示了

 

估计,使用密抄的话,这个收件人的问题没有什么好的办法了。如果有好解决方法的兄弟,告知我一声。

 

修改后的代码,请移步到前文 在php中使用SMTP通过密抄批量发送邮件,我更新在那边了。

posted @ 2010-10-25 17:02 xin478 阅读(223) 评论(0) 编辑

闲来无事,看到园子里的一篇文章约瑟夫环问题的 PHP 实现--使用 PHP 数组内部指针操作函数,以前没有搞过,也没有听说什么什么环的,所以突然也想搞一下试试

 

问题大概这样子:一群猴子排成一圈,按 1,2,...,n 依次编号。然后从第 1 只开始数,数到第 m 只,把它踢出圈,从它后面再开始数, 再数到第 m 只,在把它踢出去...,如此不停的进行下去, 直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入 m、n, 输出最后那个大王的编号。

 

脑子比较直,所以第一个想法就是这n只首尾相接排成环状的猴子,不就是一个环状链表吗? 用C的话,马上就是这个概念了。但是PHP里面没有这东西,也不能定义结构体,如果用类来实现,实际上开销有点大好像。剩下来现成点的就是数组了,虽然php中的数组实际上就是哈希表,开销也远大于C中的数组,不过,能想到的就是这家伙了。

 

原来的兄弟是用prev,next等函数来操作,但是顾名思义,prev、next每次它只能前进一步、后退一步,这样实际上就无法避免要使用循环,例如往后6个,就要运行6次的next,所以,在性能上是不划算的。很抱歉,我是用虚拟主机用惯的人,太过计较一点性能上的浪费,没办法,苦日子过惯了,见不得奢侈。

 

先申明一点,我并没有任何别的意思,原来的兄弟也说了只是想实现下并未注重算法性能

 

换一个角度看,假设说现在圈里面有5个人,我们要数12个,那么我们真的要一个一个去数,数6下?不要吧,相信大家都知道只要数2个,因为其中的10次实际上就是对圈里的5人数了2圈,在这期间,没有人会被踢出去,换句话说,这10次就是白数的。真正决定的,是后面的2次,所以,换一个方法如下:

 

function getKingMonkey1($n,$m)
{
    $a=range(1,$n); //声明一个包含n个元素的数组
    $c=$n;  //记录当前圈子中的人数
    $t=0;    //开始数数的位置
    while($c>1)  //圈中剩一个就结束
    {
    	$t=$m%$c+$t;
    	if($t>$c) $t=$t%$c;
    	$t=$t>0?--$t:0;
    	array_splice($a,$t,1);  //将不幸的兄弟踢出去
    	--$c;   //圈中人数减一
    	if($t==0) $t=$c;
    }
    return reset($a);
}

 

这个是原来的兄弟写的

//转自http://www.cnblogs.com/catprayer/archive/2010/10/04/1842085.html
function getKingMonkey($n, $m) { $a = array();//声明内部数组 for($i = 1; $i <= $n; $i ++) { $a[$i] = $i;//这一步是对号入座 } reset($a);//为了严谨,我们来一个 reset() 函数,其实也可以省去 while(count($a) > 1)//主循环开始,这里使用的判别条件是数组元素的个数等于 1 的时候停止循环 { for($counter = 1; $counter <= $m; $counter++)//嵌套的 for 循环,用来“踢出”数到 m 的猴子 { if(next($a)){//如果存在 next 元素 if($counter == $m) { unset($a[array_search(prev($a), $a)]);//当数到 m 时,使用 unset() 删除数组元素 } } else//如果不存在 next 元素 { reset($a);//则数组的第一个元素充当 next 元素 if($counter == $m) { unset($a[array_search(end($a), $a)]);//当数到 m 时,使用 unset() 删除数组元素,注意这里是 end() reset($a);//记得让数组内部指针“归位” } } } } return current($a); }

 

一、首先,用for循环为数组赋连续的值,是不划算的,用内置的range函数,就可以实现。

二、尽量避免多次调用count来获取数组数量,php中获取数组数量的方法和c#中不同,不如其高效,多次使用时,请使用局部变量来记录

三、在逻辑结构允许的情况下,++$t远比$t--来的合算,因为这点上,php是特殊的,像$t++,$t--这类的结构,它内部实际上多使用了一个局部变量来记录原值,所以,要多执行一个opcode

四、至于为什么踢出去的时候,使用array_splice而不用unset呢? 虽然unset属于语法结构,速度远比array_splice这种函数调用来的快,也都是可以将数组中的一个元素移除,但是,他们还是有不同之处。array_splice在移除数组的同时,会更改其后面索引类型为数字的元素的索引,而unset则不会。如

 

$a=array(0,1,'a'=>4,2,3,4,5,6);
array_splice($a,1,1);

则结构就由原来的
array
  0 => int 0
  1 => int 1
  'a' => int 4
  2 => int 2
  3 => int 3
  4 => int 4
  5 => int 5
  6 => int 6
变为:
array
  0 => int 0
  'a' => int 4
  1 => int 2
  2 => int 3
  3 => int 4
  4 => int 5
  5 => int 6

  换句话说,就是array_splice在移除元素之后,会对索引做一个重排,所以,在不影响使用的情况下,尽量使用unset来取代array_splice,即使是一次需要移除多个元素的情况。我这里要它重排下,所以只能依了它。

 

 

最终,运行的结果如下

在10人中数6人的情况

 

在人数及数人的数量增多的情况下,循环带来的开销会更明显,例如100人数81

 

也是过苦日子的兄弟,可以参考 优化php代码的40条建议

posted @ 2010-10-18 12:16 xin478 阅读(256) 评论(0) 编辑

这几天,在整一个php在线邮件批量发送的程序来着。如果是一人一封一封发送的话,耗时又久又资源,抄送的话,收件人就会看到其他收件人了,这种时候,密抄就最是适合了。

什么是抄送、密抄?

抄送就是将一封邮件同时发给多个收件人,各收件人都可以看到其他收件人地址。抄送效果和平时发邮件时,用“,”将地址隔开的差不多
密抄和抄送差不多,但是,各收件人都不可以看到其他收件人地址,换句话说,他收到这封邮件,根本没法知道这个是群发还是单独发送。只有发件人自己知道。

 

密抄的实现就是在邮件头里面,用Bcc加入邮件地址就可以了,如

Bcc: xin478<xin478@126.com>,xin478<44522303@qq.com>

这种情况下,该邮件就会附带发送到126和qq这两个邮箱上,但是谁都看不出来这封邮件还发给了谁。

 

因为是多用户系统,所以要求就是用户可以自己设置发送者的邮箱地址,即在我们的页面上,他可以用任何的邮箱地址来发邮件,如gmail,yahoo,126,163....,这样收件人在查看收到的邮件时,就会看到对应的发件人。

原来做的时候感觉也不是什么难事,我原来的做法是要求用户提供发件者的SMTP信息,如服务器、端口、用户名、密码,然后通过socket连接该服务器,发送邮件。在本地测试一切OK,上传到服务器,就不行了。服务器是在美国,提示unable to connect to server smtp.xxxx.com:25,大体意思是连不上指定地址及端口,一想就觉着是可能IP受限制了(因为最近被和谐的事情太多了),换了一个SMTP地址再试试,还不行,换了很多个,还不行,这才意思到不是这个问题。看字面上又像是连接被拒绝,防火墙似的拦截,不过我心想,不能啊,这个怎么能限制了,那还让不让人发邮件啊,于是又去绕弯子,最好折腾了一个下午,没结果,终于受不了了,发了一个ticket给客服问他有没有相关的限制,结果人家回过来,一看傻了

“Hello,
By default no account is allowed to connect to the SMTP servers of any other account. therefore, you should use "localhost" as the host address for SMTP and authenticate using one of your own email addresses that are listed in the cpanel.”

 

TND,他还真下得了手,限制了还hello!

那这样的话,就不能用用户提供的发件者信息来发邮件了,因为服务器的25、26端口都不能连出去。在baidu一下,发现其实很多服务器都限制了这个,因为怕用户用这个来群发垃圾邮件。

没办法,换一个方法,就是在构建邮件的header信息的时候,可以人为的指定一个发件地址,这样收件人在查看信件时,看到的收件人也是这个指定的邮件地址,就可以了。于是修改发送方固定为我们的一个邮箱,然后将用户填写的发件人加入到header信息中,好后试一下,可以。

证据:

虽然显示是发件人是noreply@yoberryks.com,实际上是通过另一个邮箱发送的。这个实际上就是在邮件头里面添加的,如果用默认的mail函数的话,这东西就修改不了了。

 

不知道网络上有没有相关的示例,我是没有看见到,所以放上相关代码,有用的人可以参考下。

以下代码因为是从自己写的框架里面直接复制出来的,缺少了必要的函数和类,如C,L,SArgumentException, MailStruct等,所以无法直接使用,仅做实现参考


这个是邮件构造类

 

<?
import('system.text.helper');
/*
 *邮件构造类,负责将邮件正文的信息编码为可供邮件发送类使用的内容(即eml内容)
 *原型代码,未严格测试,邮件附件的好像还不能用
 * @category   System
 * @package  System
 * @subpackage  Web.Mail
 * @author    xin478 <xin478@126.com>
 * @version $Id: mailstruct.class.php 42 2010-04-02 10:23 $
*/
class MailStruct
{
	private $mailCCs;	//抄送列表
	private $mailBCCs;	//暗送列表
	private $mailTo;			//收件人
	private $mailToADD;			//收件人邮箱	
	private $mailFrom;			//发件人		
	private $mailFromADD;		//发件人邮箱
	private $mailSubject;		//主题
    private $mailReplytoADD;    //回复到
	private $mailMessage;		//信件主体
	private $mailAttachments=array();	//附件
	private $isHtml=false;
	private $isNotify=false;
	private $charset='utf-8';
	private $boundary;
	
	public function __construct()
	{
		if (!defined('CRLF')) define('CRLF', "\r\n");
		$this->boundary ='====='.md5(rand()).'=====';
	}
	public function MailReplytoADD($mailaddress=null)
	{
		if( empty($mailaddress) ) return $this->mailToADD;
		else
		{
			if(!VerifyHelper::isEmail($mailaddress)) throw new SArgumentException( sprintf(L('_INVALID_EMAIL_ADDRESS'),$mailaddress) );
			$this->mailReplytoADD=$mailaddress;
		}
	}
	public function MailTo($name=null)
	{
		if( empty($name) ) return $this->mailTo; 
		else $this->mailTo=$name;
	}
	public function MailToAddress($mailaddress=null)
	{
		if( empty($mailaddress) ) return $this->mailToADD; 
		else
		{
			if(!VerifyHelper::isEmail($mailaddress)) throw new SArgumentException( sprintf(L('_INVALID_EMAIL_ADDRESS'),$mailaddress) ); 
			$this->mailToADD=$mailaddress;
		}
	}
	public function MailFrom($name=null)
	{
		if( empty($name) ) return $this->mailFrom; 
		else $this->mailFrom=$name;
	}
	public function MailFromAddress($mailaddress=null)
	{
		if( empty($mailaddress) ) return $this->mailFromADD; 
		else
		{
			if(!VerifyHelper::isEmail($mailaddress)) throw new SArgumentException( sprintf(L('_INVALID_EMAIL_ADDRESS'),$mailaddress) );
			$this->mailFromADD=$mailaddress;
		}
	}
	public function MailCC()
	{
		return is_array($this->mailCCs) && count($this->mailCCs)>0 ? $this->mailCCs : false;
	}
	public function MailBCC()
	{
		return is_array($this->mailBCCs) && count($this->mailBCCs)>0 ? $this->mailBCCs : false;
	}
	public function MailSubject($subject=null)
	{
		if(isset($subject)) $this->mailSubject=$subject;
		else return $this->mailSubject;
	}
	public function MailMessage($message=null)
	{
		if(isset($message)) $this->mailMessage=ltrim($message);
		else return $this->mailMessage;
	}
	public function IsHtml($isHtml=null)
	{
		if(isset($isHtml)) $this->isHtml=$isHtml;
		else return $this->isHtml;
	}	
	public function IsNotify($isNotify=null)
	{
		if(isset($isNotify)) $this->isNotify=$isNotify;
		else return $this->isNotify;
	}
	public function Charset($charset=null)
	{
		if(empty($charset)) return $this->charset;
		else $this->charset=$charset;
	}

    private function encodeEmail($address,$user=false)
    {
        if($user) return '<'.$address.'>';
        else return '"=?'.$this->charset.'?B?' . base64_encode( $user ) . '?=" <' . $address. '>"';
    }
	public function getHeader()
	{	
				
		$headers='';
		
		$headers.= 'Date: ' . gmdate('D, j M Y H:i:s') . ' +0000'.CRLF;
		$headers.= 'From: '.$this->encodeEmail($this->mailFromADD,$this->mailFrom).CRLF;
		if( $this->mailReplytoADD) $headers.='Reply-TO: '. $this->mailFromADD . '>'.CRLF;
        
        if( $this->mailToADD)
                $headers.= 'To: '.$this->encodeEmail($this->mailToADD,$this->mailTo).CRLF;
        
		if( is_array($this->mailCCs) && count($this->mailCCs)>0)
		{
			foreach($this->mailCCs as $k=>$v) $ccs.=' '.$this->encodeEmail($k,$v).',';
			if(isset($ccs)) $headers.='Cc: '.substr($ccs,0,-1).CRLF;
		}	 

		$headers.= 'Subject: =?'.$this->charset.'?B?' . base64_encode($this->mailSubject).'?=' . CRLF;
		$headers.= 'Message-ID: <' . time() .   '.' . $this->mailFromADD . '>'.CRLF;		
		$headers.= 'Mime-Version: 1.0'."".CRLF;  
		
		if ($this->isNotify)
			$headers.= 'Disposition-Notification-To: =?'.$this->charset.'?B?' . base64_encode($this->mailFrom) . '?='.'" <' . $this->mailFromADD . '>'.CRLF;
		
		if(count($this->mailAttachments)==0)
			$headers.= 'Content-Type: multipart/alternative;'.CRLF."\t".'boundary="'.$this->boundary.'"'.CRLF;
		else 
			$headers.= 'Content-Type: multipart/mixed;'.CRLF."\t".'boundary="'.$this->boundary.'"'.CRLF;		
		$headers.=CRLF.CRLF.CRLF;
		
		return str_replace(CRLF . '.', CRLF . '..', $headers);
		
	}
	public function getMessage()
	{	
		$bodys="";
		$bodys.= "This is a multi-part message in MIME format.".CRLF.CRLF;
		
		$bodys.= "--" . $this->boundary.CRLF;
		$bodys.= "Content-Type: text/plain;".CRLF."\tcharset=\"us-ascii\"".CRLF;
		$bodys.= "Content-Transfer-Encoding: base64".CRLF.CRLF;
		$bodys.= base64_encode(strip_tags(str_replace('<br/>',"\n",$this->mailMessage))).CRLF.CRLF;
		
		$bodys.= "--" . $this->boundary.CRLF;
		
		if($this->isHtml)
		{
			$bodys.= "Content-Type: text/html;".CRLF."\tcharset=\"us-ascii\"".CRLF;
			$bodys.= 'Content-Transfer-Encoding: base64'.CRLF.CRLF;
			$bodys.=base64_encode($this->mailMessage).CRLF.CRLF;
		}
        
		foreach($this->mailAttachments as $filename)
		{				
			$contentType = self::getContentType($filename);
			$attachment = base64_encode(file_get_contents($filename));
			$attachment = chunk_split($attachment);
			
			$bodys.= "--".$this->boundary.CRLF; 
			$bodys.= "Content-type: " . $contentType . "; name=".basename($filename) .CRLF;
			$bodys.= "Content-disposition: attachment; filename=".basename($filename) .CRLF;
			$bodys.= "Content-transfer-encoding: base64".CRLF.CRLF;
			$bodys.= $attachment .CRLF.CRLF;
		} 
		$bodys.= "--" . $this->boundary."--".CRLF;
		
		$bodys    = str_replace(CRLF . '.', CRLF . '..', $bodys);
		$bodys    = substr($bodys, 0, 1) == '.' ? '.' . $bodys : $bodys;

		return $bodys;
	}
	public function addBCC($mailaddress,$name=null)
	{
		if(!VerifyHelper::isEmail($mailaddress)) throw new SArgumentException( sprintf(L('_INVALID_EMAIL_ADDRESS'),$mailaddress) ); 
		
		$address=strtolower($mailaddress);
		$this->mailBCCs[$address]= empty($name)? substr($address,0, strpos($address,'@')) : $name;
	}
	public function addCC($mailaddress,$name=null)
	{
		if(!VerifyHelper::isEmail($mailaddress)) throw new SArgumentException( sprintf(L('_INVALID_EMAIL_ADDRESS'),$mailaddress) ); 
		
		$address=strtolower($mailaddress);
		$this->mailCCs[$address]= empty($name)? substr($address,0, strpos($address,'@')) : $name;
	}
	public function addAttachments($path)
	{
		if(!in_array($path,$this->mailAttachments)) $this->mailAttachments[]=$path;
	}
	
	static function getContentType($inFileName)
	{   
		//--去除路径   
		$inFileName = basename($inFileName);   
		//--去除没有扩展名的文件   
		if(strrchr($inFileName, ".") == false)
		{  
			return "application/octet-stream";  
		}  
		//--提区扩展名并进行判断   
		$extension = strrchr($inFileName, ".");   
		switch($extension){   
			case ".gif": return "image/gif";  
			case ".gz": return "application/x-gzip";  
			case ".htm": return "text/html"; 
			case ".html": return "text/html";   
			case ".jpg": return "image/jpeg";   
			case ".tar": return "application/x-tar";   
			case ".txt": return "text/plain";   
			case ".zip": return "application/zip";   
			default: return "application/octet-stream";   
		}     
	}  
	
} 
?>

 

 

 这个是邮件发送类

 

<?php
/**
 * 利用SOCKET发送SMTP邮件
 * 因为是从自己写的框架里面直接复制出来的,直接使用不能使用,少了几个函数和类,如C,L,SArgumentException等,所以仅做参考
 */

class SocketSmtp
{

	private $host,$port,$user,$pass,$auth;
	private $timeout = 10;
	private $socket;
	private $helo='localhost';
	private $status=0;
	
	public function __construct($host,$user='',$pass='',$port=25,$auth=1)
	{
		if (!defined('CRLF')) define('CRLF', "\r\n");
		$this->host=$host;
		$this->port=$port;
		$this->helo=$host;
		$this->user=$user;
		$this->pass=$pass;
		$this->auth=$auth;
	}
	
	/**
     * 获取或设置连接超时时长(秒)
     * @param <int> $second
     * @return <int> 
     */
    public function timeOut($second=null)
	{
		if( is_numeric($second) && $second>0) $this->timeout=$second;
		else return $this->timeout;
	}

    /**
     * 发送指定邮件并返回是否成功
     * @param MailStruct $mail
     * @return <bool>
     */
	public function Send($mail)
	{
		if(! $mail instanceof MailStruct) throw new SArgumentException(L('_INVALID_ARGUMENT_TYPE_','MailStruct'),$mail);		
		
		if(!$this->connect() || !$this->auth() || !$this->mail( $mail->MailFromAddress() )) return false;

        $arrToEmail = array();
		if($mail->mailCC() )
		{
			$ccs=array_keys($mail->mailCC());
			$arrToEmail = array_merge($arrToEmail,$ccs );
		}
		if($mail->mailBCC() )
		{
			$bccs=array_keys($mail->mailBCC());
			$arrToEmail = array_merge($arrToEmail, $bccs);
		}

        if($mail->MailToAddress() ) $this->rcpt($mail->MailToAddress());


		foreach($arrToEmail as $toEmail)
		{
			$this->rcpt($toEmail);
		}
		if (!$this->data()) return false;
				
		$this->send_data($mail->getHeader());
		$this->send_data('');
		$this->send_data($mail->getMessage());
		$this->send_data('.');
		
		return (substr($this->get_data(), 0, 3) === '250');		
	}

    /**
     * 关闭连接到服务的链接
     */
	public function close()
	{
		if($this->socket!=null)
		{
			$this->send_data('QUIT');
			@fclose($this->socket);
			$this->status=0;
			$this->socket = null;
		}
	}
	
	private function mail($from)
	{
		if ($this->send_data('MAIL FROM:<' . $from . '>')
				&& substr($err=$this->get_data(), 0, 3) === '250' )
		{
			
			return true;
		}
		else
		{
			return false;
		}
	}
	
	private function auth()
	{
		if($this->status<2) return false;
		
		if(!$this->auth) return true;
		
		if (is_resource($this->socket)
				&& $this->send_data('AUTH LOGIN')
				&& substr($error = $this->get_data(), 0, 3) === '334'
				&& $this->send_data(base64_encode($this->user))            // Send username
				&& substr($error = $this->get_data(),0,3) === '334'
				&& $this->send_data(base64_encode($this->pass))            // Send password
				&& substr($error = $this->get_data(),0,3) === '235' )
		{
			$this->status=3;
			return true;
		}
		else
		{
            throw new SystemException( L('_ERROR_AUTHORIZE_'), trim(substr($error, 3)));			
			return false;
		}
	}
	
	private function rcpt($to)
	{
		if ($this->send_data('RCPT TO:<' . $to . '>') && substr($error = $this->get_data(), 0, 2) === '25')
		{
			return true;
		}
		else
		{
            throw new SystemException( L('_ERROR_COMMAND_RESPONSE_'), trim(substr($error, 3)));
			return false;
		}
	}
	
	private function data()
	{
		if (is_resource($this->socket) && $this->send_data('DATA') && substr($error = $this->get_data(), 0, 3) === '354' )
		{
			return true;
		}
		else
		{
			throw new SystemException( L('_ERROR_COMMAND_RESPONSE_'), trim(substr($error, 3)));
			return false;
		}
	}	
	
	private function send_data($data)
	{
		return fwrite($this->socket, $data . CRLF, strlen($data) + 2);
	}
	
	private function get_data()
	{
		$return = '';
		$line   = '';
		
		if (is_resource($this->socket))
		{
			while (strpos($return, CRLF) === false OR $line{3} !== ' ')
			{
				$line    = fgets($this->socket, 512);
				$return .= $line;
			}
			
			return trim($return);
		}
		else
		{
			return '';
		}
	}
	
	private function connect()
	{
		if( $this->status>0 && is_resource($this->socket)) return true;
		
		$this->socket = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
        if(!$this->socket) throw new SystemException( L('_CONNECT_SERVER_FAIL_'),$errstr);

        $this->get_data();
        @stream_set_timeout($this->socket, 0, 250000);
        $this->status=1;
        $cmd=$this->auth ?'EHLO ':'HELO ';
		
        if( $this->send_data($cmd . $this->helo) && substr($error = $this->get_data(), 0, 3) === '250')
        {
            $this->status=2;
            return true;
        }
        else
        {
            throw new SystemException( L('_ERROR_COMMAND_RESPONSE_'),  trim(substr($error, 3)));
            return false;
        }
		
	}
}
?>

 

调用的方法如下

 

<?php
$m=new MailStruct();
$m->MailSubject('test topic'); //设置标题
$m->MailMessage('this is content '); //设置正文
$m->isHtml(1); //以HTML发送
$m->MailTo('xin478'); //收件人姓名
$m->MailToAddress('44522303@qq.com'); //收件人地址
$m->MailFromAddress('xin478@126.com'); //发件人地址
$m->MailFrom( 'xin478'); //发件人姓名
$m->addBCC('bcc1@test.com','bcc person 1'); //添加密抄
$m->addCC('cc2@test.com','cc person 2'); //添加抄送
$sock=new SocketSmtp('smtp.xxx.com','user','password',25);
$sock->Send($m);
$sock->close();
?>
posted @ 2010-10-15 10:46 xin478 阅读(634) 评论(0) 编辑

      早先在asp横行的年代,php和asp一样,大都都是html中夹杂代码,说实话,这时候IDE的确用处不是很大,倒是类似于dw之类的设计器甚为上手。现在,三层、mvc之类的思想遍地开花,使得代码和html得以分离,加之随着开发的分工和项目的增大,一个好的IDE能为编码工作提供了许多的便利。就像开发java用eclipse,.NET用visual studio一样,开发PHP也很需要一种这样的利器。常见的php的IDE有Eclipse,NetBeans,Zend studio,vs.php等。这几个我也都用过,其中Eclipse,NetBeans,Zend studio都有win和linux的版本,也都集成了像代码感知、调试、设计、片段等的功能,都用过一阵子后发现,在windows下,个人感觉还是vsiual studio+vs.php最是好使。主要的原因就是速度。 vs的速度真的是快其他的IDE太多了,无论是从启动速度还是使用过程中资源的耗用都要好于其他3款,毕竟是微软自家的东西。

      vs.php以插件形式安装到vs,现在已经出到2.9,支持visual studio2005~2010,到官网下载安装即可。默认是30天试用,可以搭配visualstudio express。安装以后,在visual studio的新建项目里就会多出来php的项目。

image

当然也支持一个解决方案,多个项目。

image

 

vs.php在启动的时候,会自动扫描包含在项目里的php文件,并加载到代码自动感知里。同时,未避免加载太多的感知支持,默认并没有加载不常用的php扩展的感知支持,如果有需要的话,可以右键项目,选择Add Php Module, 在列表里选择要添加的扩展,如图。 如果要对项目外的文件添加感知,也可以通过右键项目,选择Add Php Refence,选择文件添加支持。

image

 

需要调试的话,可以编辑项目属性,这里的话,有个不太好的地方就是Start page一定要设置,不然无法启动调试,而且按F5运行调试时,就是打开这个起始页,没办法像ASP.NET那样,运行当前打开的页面。

image

你可以根据需要选择调试的模式等配置,当然,如果你觉得有的东西老改麻烦的话,也可以通过修改vs.php的配置来一劳永逸。vs.php内带了一个apache2.2在安装目录下,所以,选择调试的时候,你可以决定用内置的apache还是服务器的apache,同时,安装目录下有PHP4,PHP5的目录,里面的东西也可以修改使用,诸如php.ini。如果使用xdebug来调试的话,推荐修改下php5下的php-xdebug.ini,添加修改下

[XDebug]
xdebug.idekey = vsphp
xdebug.auto_trace=On
xdebug.collect_params=On   
xdebug.collect_return=On   
xdebug.trace_output_dir="d:/x-debuginfo"
xdebug.profiler_enable=On    ;打开效能监测器
xdebug.profiler_output_dir="d:/x-debuginfo"   
xdebug.default_enable = On
xdebug.show_mem_delta=On

 

这样,调试时就会输出调试信息到d:/x-debuginfo,再使用WinCacheGrind来查看这个执行的CPU,内存使用情况,函数执行时间,尤其方便进行性能优化。如

image

Language Reference目录下存放的是php的函数注解,智能感知就依赖这些文件,修改里面的注释信息,就可以改变感知时的提示,现在是全英文的,不知道会不会出一个中文的注释,期待。

 

在代码智能感知方面,vs.php只能打到80分这样,有的时候出不来是比较郁闷的。当然,这可能与你将类或函数分布在其他的文件里有关系,vs.php会自动解析require,include等的包含语句,并尝试加载解析这个文件,在使用实例化对象时,在当前的信息不足时,会尝试按照项目配置属性里的设置加载该文件

image

就如同php里面的__autoload。

 

另外,规范合理的注释将为代码感知的提示提供极大的便利,尤其是对于自定义的类对象,尤为有效。就比如说,

image

这里的$this->response,他并不知道是什么类型,所以任何提示都不会有,但是如果加上了类型声明 @var 类型, 那就可以正常显示该对象的成员信息、提示等

image

在断点调试方面,虽然有时候无法捕获断点,但是也算是实现了。

image

 

其实很多时候,因为这个功能的不够可靠,这种情况我还是倾向于自己输出变量查看。

 

总的说来,个人比较喜欢vs.php,相比zendstudio,NetBeans等的运行速度和资源占用,这无疑是更好的选择。而且,我个人喜欢使用ASP.NET的页面搭配smarty的语法作为php的模板,比起纯粹的html模板,.NET的页面在visualstudio里面有着无可比拟的优点,例如Masterpage和usercontroller,都能正常显示,这个对于控件复用和设计而言,相当的方便。具体的模板类,有空的时候整理下再放出。

如果你还在用记事本啦,Dreamweaver之类的,不妨试试vs。

posted @ 2010-08-15 10:04 xin478 阅读(650) 评论(1) 编辑
摘要: 对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法。同样,在mysql里,也有类似的hint功能。下面介绍一些常用的。 强制索引 FORCE INDEX SELECT * FROM TABLE1 FORCE INDEX (FIELD1) … 以上的SQL语句只使用建立在FIELD1上的索引,而不使用其它字段上的索引。 忽略索引 IGNORE...阅读全文
posted @ 2010-08-13 09:49 xin478 阅读(48) 评论(0) 编辑
摘要: 公司有几个网站搭在美国的虚拟主机上,服务器上的mysql服务差不多每一天都会突然不知什么时候挂掉,然后过一会又恢复了,怀疑是超出cpu的使用限制而被自动结束了,但是实际上该服务器上的流量很小。于是早先的时候联系了服务器提供商的印度阿三客服,想看看是不是其他用户搞多了害的大家一起死,阿三们查找了之后,信誓旦旦的拍着长毛的胸部保证不是他们的问题,事情没有解决。悬着不是个事,只好自己查了,好在可以访问到...阅读全文
posted @ 2010-08-03 15:54 xin478 阅读(194) 评论(2) 编辑
摘要: 其实windows下php的安装配置是比linux下容易多了,加之三兄弟都是绿色的,重装系统的时候只需解压注册一下相应的服务就可以了,本方法适合初学者参考。第一次使用的对于php,直接到php官网下载并解压就可以了。这里假定解压在d:\php5\找到d:\php5\下的php.ini文件,如果没有的话,可以用php.ini-xxxxxxx的文件(php.ini-development是开发时的配置...阅读全文
posted @ 2010-05-07 11:57 xin478 阅读(718) 评论(0) 编辑
摘要: 去年的这个时候搞了一个紫光创奇MS621S,闲来无事的时候看看动画,屏幕小点但也混合。最近用久了不稳定得很,老容易卡死,可能跟我常突然拔出有关系,也可能是这家伙快挂了,前几天想找一个新的固件更新下,顺便把闪存部分修复下,没想到事大了。先说紫光的东西,这个家伙其实不做这个,在市面上的十有八九是假的,那时候就是买个杂牌。如果你去店里面买数码产品,要便宜点的,老板指定给你紫光。先不声讨这个,既然是杂牌,...阅读全文
posted @ 2009-12-08 20:09 xin478 阅读(450) 评论(0) 编辑
摘要: POP协议简介本文简要说明了通过POP3协议收取邮件、MIME邮件的解码的原理;针对收取和MIME解码,提供了两个实用的PHP类,并提供了使用的样例。分为邮件收取、MIME解码两个部分。这里我们先向您介绍邮件的收取,解码部分会在以后的文章中为各位详细的介绍,敬请关注。 现在Internet上最大的应用应该是非Email莫属了,我们每天都习惯于每天通过Email进行交流,各大网站也几乎都推出了自己的...阅读全文
posted @ 2009-07-03 15:00 xin478 阅读(470) 评论(0) 编辑