2006年12月15日

要把这个中文字符串拆成单个字符,可以这样写:
use Encode;
use Encode::CN; #可写可不写
$dat=”测试文本”;
$str=decode(“gb2312”,$dat);
@chars=split //,$str;
foreach $char (@chars) { print encode(“gb2312”,$char),”\n”;
}

2005年09月23日

张向宁搞了个窄告,据说已经占据了新浪、TOM、中华网、人民网、新华网、中国新闻网等上千家顶级网络媒体新闻最终页的广告资源。

本人看了一下所谓的窄告,发现比“广告”窄多了,且不说这个概念或者做法到底是张提出的还是google先做的。我之所以说它真的很窄,且看一个例子。

我们随便从donew上打开一片文章来看,下面就是那个著名的narrowad啦。 narrowad的广告首先是闪动的中国万网和戴尔促销,其中万网是铁打不动的了,自家做广告,当然肥水不流外人田,而旁边的戴尔则是说明,窄告并不是自己宣传的阵地。

下面过场的3段广告,大致分类一下:第一屏:包括“90天给女人双倍的爽”等一系列医院、旅游等无关广告,应该全部是交钱刊登的,跟当前浏览文章内容的关键字毫无关系。

第二屏:中国总机,正屏仅此一个广告,看来是花了不少钱。同样,跟当前文章关键字毫无关系。

第三屏:大概有5个。关键字与当前浏览文章相同,为什么只有5个,而不是6个,因为第一个是万网的广告,再次无语。从技术角度来讲,是个程序员就会写这种广告。拿广告商的关键字和当前文章的关键字对比,相同的就刊登,甚至连个分类都没有,拿donews上的李开复:web2.0是一种用户体验的包装一文,下面的关键字广告分别是:专业塑料生产,上海众和包装机械,zope/plone中文社区,中国市场信息网,无微不至的关怀。

那么我算一下广告的命中率。

在此文章下面投放的窄告,其中广告总数为:23个,其中万网和戴尔促销重复了,各占用了2个广告。而与本文关键字贴边的广告有(本文关键字为:web IT 包装 平台)1个,就是那个ZOPE/PLONE中文社区,起码跟IT技术贴边,其他的都无法属于命中目标。尤其是那个专业塑料生产企业,其关键字居然是IT。看来窄告再征广告的时候,要注意人家提交的关键字噢。

那么,从广告数量上来讲,23个广告中只有1个命中,其命中率我就不算了。

再从浏览时间上来讲,刷动的3屏广告大概花费时间20秒。20秒中可以说至少花了15秒再看与本文关键字完全不沾边的“垃圾广告”。

总结一下,从最终效果上来看,窄告与广告没什么区别,张向宁玩的就是概念。如果我想让我的广告精确命中,我不会选择窄告。因为它真的很窄,命中率奇低~~~~~

2005年09月11日

葡萄酒在瓶中也是一个陈年的过程,葡萄酒的保存自然而然就关系到葡萄酒在瓶中陈年的质量。葡萄酒的保存一般要注意的几个方面是:温度、湿度、光线和振动。

  第一个最要紧的因素就是温度,葡萄酒最佳的保存温度应该是13度左右,曾经有学者作过专门的分析,认为理想温度是摄氏12.8度,这有一点太绝对化了。加州大学化学系教授AlexanderJ.Pardell曾经做过试验研究,如果以摄氏13度作为基准,如果温度上升到摄氏17 度,酒的成熟速度会是原来的1.2~1.5倍,如果温度增加到23摄氏度,成熟速度将变成2~8倍,温度升高到32摄氏度,成熟速度将变为4~56倍。当然成熟速度的变化也和酿酒所用葡萄品种,和酿造法不同而不同。另外,温度最好要保持恒定,变化很大的温度,对酒的伤害也是很大的。

  有人也许会问,温度稍微高一点,酒的成熟速度快,这样需要比较长时间成熟的酒,不是很快就可以喝了吗?其实,成熟速度快,会让酒的风味比较粗糙,而且有时会发生过分氧化让酒变质的可能。

  湿度的影响主要作用于软木塞,湿度一般认为在60~70%是比较合适的,湿度太低,软布塞会变得干燥,影响密封效果,让更多的空气与酒接触,加速酒的氧化,导致酒变质。即使酒没有变质,干燥的软木塞在开瓶的时候很容易断裂甚至碎掉,那时就免不了有很多木屑掉到酒里,这可是有点令人讨厌的事情。如果湿度过高有时也不好,软木塞容易发霉,而且,在酒窖里的话,还容易滋生一种甲虫,这种象虱子大小的甲虫会把软木塞咬坏。

  光线中的紫外线对酒的损害也是很大的,因此想要长期保存的葡萄酒应该尽量放到避光的地方。虽然葡萄酒的墨绿色瓶子能够遮挡一部分紫外线,但毕竟不能完全防止紫外线的侵害。紫外线也是加速酒的氧化过程的罪魁祸首之一。

  振动对酒的损害纯粹是物理性的,葡萄酒装在瓶中,其变化是一个缓慢的过程,振动会让葡萄酒加速成熟,当然结果也是让酒变得粗糙。所以应该放到远离振动的地方,而且不要经常地搬动。

  由以上几点可以看出来,保存葡萄酒最好的地方就是酒窖,有一定的深度可以保证恒温,避光,远离振动源,当然如果温度不合适,可以安装调温设备。但是,恐怕一般人都没有这个条件自己挖一个地窖。

  第二个选择就是电子酒柜。这和普通的冰箱不同。普通的冰箱的控温设备是将温度降到一定温度以下比如2、3度,然后,等温度升到6、7度左右的时候再启动。这样有几个不好的地方,第一个是温度有波动,而且也太低。第二个就是冰箱这种大幅度的温度波动,在冷凝器表面会结霜,即使冰箱里面没有除湿设备,也会因为这个让湿度大大降低。第三个问题是一般的冰箱一般不具有抗震设计,因此启动的时候会有振动。专业的电子酒柜是恒温恒湿而且避震的,但是价格也非常的贵。比如最专业级的EuroCave牌的酒柜,装50瓶酒的最小的一种也需要900块美金。国内只有海尔制作酒柜,但是只有恒温,没有恒湿,避震方面恐怕也不行,不过如果自己做一些小小的改进,问题还好解决。其他还有没有性能价格比高的酒柜了?我还没看到过,有谁知道,大家分享一下信息,好东西要和大家分享嘛!

  最后要说的是酒瓶的摆放了。大家都知道葡萄酒要横放,其实,瓶口向上倾斜15度也是可以的。我个人认为,瓶口向下的摆放方法并不可取,尤其是需要储存比较长的时间的红酒。原因就是红酒存放时间长了,就会有沉淀,平放或者瓶口向上略微倾斜,沉淀就会聚集在瓶自底部,而如果瓶口向下倾斜,那沉淀就会聚集在瓶口处,时间长了还会粘在那里,倒酒的时候,会连沉淀一起倒入酒杯。因此,我个人觉得不太可取。

  某位聪明的酿酒商说:“品酒与喝酒珠区别在于思考。”在西方,品酒被视为一种高雅而细致的情趣,鉴赏葡萄酒更是有钱阶层的风雅之举。其实,品酒并不复杂,可分为四个步骤:一观,二摇,三嗅,四尝。只要有敏锐的感觉和灵性,付出相应的耐心和时间,您也可以领略其中的玄妙悠然。
  第一步:观色
  在酒器背后衬白纸或白色餐巾有助于观察葡萄酒的色泽。新酒颜色清晰鲜明,陈酒呈现轻微的黄褐色。白葡萄酒陈年时间越长,色泽越深;红葡萄陈年时间越长,色泽越浅。
  第二步:遥晃
  手握酒杯底托,不停地摇晃杯中酒,使氧气与葡萄酒充分融合,最大程度地释放出葡萄酒的独特香气。
  第三步:嗅味
  葡萄酒的气味部分来自用于酿酒的新鲜葡萄,部分源于酿制方法。好酒的香气是持久而丰富的,有花草香、果实香、烤肉香、皮革香、泥土香、橡木桶香。
  第四步:品尝
  将酒液啜入一小口放于口腔前部,让舌头相关部分把酒液温热,使各种香味缓缓逸出,渐入佳境。通常会感到下列味道相互糅合:

  甜味(不甜的称为“干”)
  大部分红葡萄酒和某些白葡萄酒属于干性。提前终止发醇的酒会留下一些天然糖分。舌尖若明显感触到糖分,便属于微甜至十分甜的葡萄酒。

  酸味
  可于舌头两侧和颚部位感觉到。白葡萄酒呈现出酸度非常普遍。

  涩味
  葡萄的皮和籽皆含有丹宁(Tannin)。丹宁是一种可在茶、菠菜等植物中的带苦涩味的化合物。红葡萄酒丹宁含量最高,白葡萄酒最低。

  酒精
  酒液流进喉咙时,会弥漫一股暖气。酒精越多,温暧感越强。

一忌与海鲜为伍

  红葡萄酒配红肉符合烹调学自身的规则,葡萄酒中的单宁与红肉中的蛋白质相结合,

使消化几乎立即开始。尽管新鲜的大马哈鱼、剑鱼或金枪鱼由于富含天然油脂,能够与体量轻盈的红葡萄酒搭配良好,但红葡萄酒与某些海鲜相搭配时,比如:多弗尔油鳎鱼片,高含量的单宁会严重破坏海鲜的口味,葡萄酒自身甚至也会带上令人讨厌的金属味。

  白葡萄酒配白肉类菜肴或海鲜也是通用的好建议。一些白葡萄酒的口味也许会被牛肉或羊肉所掩盖,但它们为板鱼、虾、龙虾或烤鸡胸脯佐餐都会将美味推到极高的境界。

  二忌有醋相伴

  各种沙拉通常不会对葡萄酒的风格产生影响,但如果其中拌了醋,则会钝化口腔的感受,使葡萄酒失去活力,口味变得呆滞平淡。柠檬水是好的选择,这是因为其中的柠檬酸与葡萄酒的品格能够协和一致。

  奶酪和葡萄酒是天生的理想组合,只需注意不要将辛辣的奶酪与体量轻盈的葡萄酒相搭配,反之亦然。

  三、浓香辛辣食品配酒有挑选

  辛辣或浓香的食品配酒可能有一定难度,但搭配辛香型或果香特别浓郁的葡萄酒,可算找对了伴侣。

  巧克力有时也对葡萄酒口味有不利的影响,有些人宣称配陈年的赤霞珠葡萄酒能够获得成功。班费巴切托得阿奎葡萄酒配巧克力尤其是黑巧克力效果极佳、令人欣喜。这款意大利葡萄酒果香细腻而爽脆,恰到好处的天然酸度足以平衡巧克力的馥郁与香甜,同时又使你的口腔保持舒适的清爽与洁净。

2005年09月09日
谈谈POP3协议工作模式和原理
作者:梦想 发文时间:2004.10.26
    在日常的生活中,书信往来是我们日常生活中不可缺少的一个环节。随着Internet的普及,传统信件的Internet版本——电子邮件已经逐渐步入了我们的生活与工作。在平日我们收取普通邮件的时候,我们常常会用一把带锁的箱子作为我们自己的信箱,而我们平日使用的电子邮件也有它们的暂时存放地——POP服务器。与传统邮件进行类比,我们使用账号和口令打开POP服务器就好比是我们在日常生活中打开自己平日的信箱一样,下面就让我们一起来看看如何使用POP服务器吧。

    什么是POP

    大家一听这个POP,读起来有点像是中文中的泡泡,其实这是一个英文术语的缩写。POP的全称是 Post Office Protocol,即邮局协议,用于电子邮件的接收,它使用TCP的110端口。现在常用的是第三版 ,所以简称为 POP3。POP3仍采用Client/Server工作模式,Client被称为客户端,一般我们日常使用电脑都是作为客户端,而Server(服务器)则是网管人员进行管理的。举个形象的例子,Server(服务器)是许多小信箱的集合,就像我们所居住楼房的信箱结构,而客户端就好比是一个人拿着钥匙去信箱开锁取信一样的道理。

    POP在网络模型中的层次

    大家都知道网络是分层的,而这个分层就好比是一个企业里的组织结构一样。在日常使用电脑过程中,人操作着电脑,人就好比是指挥电脑对因特网操作的首席执行官。当我们打开Foxmail这个邮件软件收取邮件时,Foxmail这个软件就会调用TCP/IP参考模型中的应用层协议—POP协议。

    应用层协议建立在网络层协议之上,是专门为用户提供应用服务的,一般是可见的。如利用FTP(文件传输协议)传输一个文件请求一个和目标计算机的连接,在传输文件的过程中,用户和远程计算机交换的一部分是能看到的。而这时POP协议则会指挥下层的协议为它传送数据服务器,最后Foxmail通过一系列协议对话后成功将电子邮件保存到了Foxmail的收件箱里。TCP/IP参考模型是Internet的基础。和OSI的7层协议比较,TCP/IP参考模型中没有会话层和表示层。通常说的TCP/IP是一组协议的总称,TCP/IP实际上是一个协议族(或协议包),包括100多个相互关联的协议,其中IP(Internet Protocol,网际协议)是网络层最主要的协议;TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协议)是传输层中最主要的协议。一般认为IP、TCP、UDP是最根本的三种协议,是其它协议的基础。

    相信读者了解TCP/IP框架之后,一定会对各层产生一定的兴趣,不过我们对于这个模型的理解也是一步步来的。在这里,我们首先只要知道相应的软件会调用应用层的相应协议,比如Foxmail会调用POP协议,而IE浏览器则会调用DNS协议先将网址解析成IP地址。在实际收取邮件的过程中,POP这个应用层的协议会指挥TCP协议,利用IP协议将一封大邮件拆分成若干个数据包在Internet上传送。

    为了便于读者理解这个过程,笔者举个例子来说明一下,比如你要和一个人远距离通话,因为距离实在太远了,你只好将你所表达的一大段分成一个个字大声喊,而对方把每个听到的字写在纸上,当写下来后就大喊一声告诉你它收到了,这样就克服了距离远听不清的弱点,这种一问一答的反馈机制就好比是TCP协议,POP服务器一般使用的是TCP的110号端口。

    POP工作原理简介

    下面就让我们一起来看看电子邮件软件收取电子邮件的过程,一般我们在电子邮件软件的账号属性上设置一个POP服务器的URL(比如pop.163.com),以及邮箱的账号和密码。这个在收信过程中都是用得到的。当我们按下电子邮件软件中的收取键后,电子邮件软件首先会调用DNS协议对POP服务器进行解析IP地址,当IP地址被解析出来后,邮件程序便开始使用TCP协议连接邮件服务器的110端口,因为POP服务器是比较忙的,所以在这个过程中我们相对要等比较长的时间。当邮件程序成功地连上POP服务器后,其先会使用USER命令将邮箱的账号传给POP服务器,然后再使用PASS命令将邮箱的账号传给服务器,当完成这一认证过程后,邮件程序使用STAT命令请求服务器返回邮箱的统计资料,比如邮件总数和邮件大小等,然后LIST便会列出服务器里邮件数量。然后邮件程序就会使用RETR命令接收邮件,接收一封后便使用DELE命令将邮件服务器中的邮件置为删除状态。当使用QUIT时,邮件服务器便会将置为删除标志的邮件给删了。通俗地讲,邮件程序从服务器接收邮件,其实就是一个对话过程,POP协议就是用于电子邮件的一门语言。
POP3协议封装类
2002-03-07· ·贾旭滨(译)··

  目前互连网上,EMAIL的使用是越来越广泛了。在所有的TCP连接线路中,大概有一半的线路是用来收发EMAIL的。因此,许多网络应用程序要想离开POP3协议是不可能的。

  而且,很多EMAIL系统都是使用SMTP协议来作为发送协议,而POP3协议来作为接受协议。关于这2个协议的许多资料,你可以看一下RCF821(关于SMTP的)和RCF1225(关于POP3的)。虽然在WINDOWS操作系统中,有一个叫MAPI应用程序是来管理EMAIL的,但是它的功能还不够强大,不足以直接处理一些EMAIL服务。所以,我写了一个有关于POP3协议的C++类,在这个类中我还使用了CSocket作为一个类成员(这好象有点不可想象),这样的话呢,我们可以在连接的时候使用它。并且,该POP类使用的一些功能类似于POP3协议中的一些命令。下面就代码:


/*——————————————————————–
Pop.h : main header file for the POP application
———————————————————————–*/

#if !defined(AFX_POP_H__A44B38B6_697C_11D1_881E_00001C302581__INCLUDED_)
#define AFX_POP_H__A44B38B6_697C_11D1_881E_00001C302581__INCLUDED_

#define CONNECTION_CHECK 0
#define USER_CHECK 1
#define PASSWORD_CHECK 2
#define QUIT_CHECK 3
#define DELETE_CHECK 4
#define RSET_CHECK 5
#define STAT_CHECK 6
#define NOOP_CHECK 7
#define LIST_CHECK 8
#define RETR_CHECK 9

/////////////////////////////////////////////////////////////////////////////
class CPop
{
public:
BOOL List();
CWordArray m_SizeOfMsg;
CString GetErrorMessage(); // If there is any error this will return it method
CString GetPassword(); // Getting Password stored in class
void SetPassword(CString& Password); // Setting Password in class
CString GetUser(); // Getting user name stored in class
void SetUser(CString& User); // Setting user name in class
CString GetHost(); // Getting Host name (email server name) stored in class
void SetHost(CString& Host); // Setting Host name (email server name) in class
BOOL Connect(); // Connecting to email server
int GetTotalMailSize(); // it returns the Total Mail Size
int GetNumberOfMails(); // It return the number of mails
CString GetMsgContents();
BOOL Statistics(); // issue the STAT command on email server
BOOL Retrieve(int MsgNumber); // Getting any particular mail message
BOOL Reset(); // issue the reset command on email server
int GetMessageSize(int MsgNumber); // Return a size of any particular mail
BOOL Noop(); // issue the NOOP command on email server
BOOL Disconnect(); // issue the QUIT command on email server
BOOL Delete(int& MsgNumber); // Deleteing a particular message from email server
BOOL Connect(CString& Host, CString& User, CString& Password);
CPop();
virtual ~CPop();

private:
CString m_ErrorMessage;
BOOL CheckResponse(int ResponseType);
CString m_Password;
CString m_User;
CString m_Host;
CString m_MsgContents;
int m_TotalSize;
int m_NumberMail;
CSocket m_PopServer;
};
/#endif // !defined(AFX_POP_H__A44B38B6_697C_11D1_881E_00001C302581__INCLUDED_)


/*———————————————————————————————–
// Pop.cpp : Defines the class behaviors for the application.
—————————————————————————————————*/

#include "stdafx.h"
#include "Pop.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

////////////////////////////////////////////////////////////////////
// CPop Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPop::CPop()
{
m_PopServer.Create();
}
//{4EEC1C91-6BE1-11d1-8824-00001C302581}

CPop::~CPop()
{
m_PopServer.Close();
}

BOOL CPop::Connect(CString & Host, CString & User, CString & Password)
{
char buf [512];

if (!m_PopServer.Connect(Host,110)) // 110 Pop3 Port
{
m_ErrorMessage = _T("Server cannot be connected");
return FALSE;
}
else
{
if(CheckResponse(CONNECTION_CHECK)==FALSE)
return FALSE;

wsprintf (buf, "USER %s\r\n", (LPCSTR) User);
m_PopServer.Send(buf, strlen (buf));
if(CheckResponse(USER_CHECK)==FALSE)
return FALSE;

wsprintf (buf, "PASS %s\r\n", (LPCSTR) Password);
m_PopServer.Send(buf, strlen (buf));
if (CheckResponse(PASSWORD_CHECK)==FALSE)
return FALSE;

return TRUE;
}

}

BOOL CPop::Delete(int & MsgNumber)
{
char buf [512];

wsprintf (buf, "DELE %d\r\n",MsgNumber );
m_PopServer.Send(buf, strlen (buf));
if (CheckResponse(DELETE_CHECK)==FALSE)
return FALSE;
else
return TRUE;
}

BOOL CPop::Disconnect()
{
char buf [512];

wsprintf (buf, "QUIT \r\n");
m_PopServer.Send(buf, strlen (buf));
if (CheckResponse(QUIT_CHECK)==FALSE)
return FALSE;
else
return TRUE;
}

BOOL CPop::Noop()
{
char buf [512];

wsprintf (buf, "NOOP \r\n");
m_PopServer.Send(buf, strlen (buf));
if (CheckResponse(NOOP_CHECK)==FALSE)
return FALSE;
else
return TRUE;
}

// Return the Msg Size for given msg number
int CPop::GetMessageSize(int MsgNumber)
{
if(m_SizeOfMsg.GetSize() < MsgNumber+1)
return 0;
else
return m_SizeOfMsg[MsgNumber+1];
}

BOOL CPop::Reset()
{
char buf [512];

wsprintf (buf, "RSET \r\n");
m_PopServer.Send(buf, strlen (buf));
if (CheckResponse(RSET_CHECK)==FALSE)
return FALSE;
else
return TRUE;
}

// MsgContents will hold the msg body
BOOL CPop::Retrieve(int MsgNumber)
{
char buf [512];

wsprintf (buf, "RETR %d\r\n",MsgNumber );
m_PopServer.Send(buf, strlen (buf));
if (CheckResponse(RETR_CHECK)==FALSE)
return FALSE;
else
return TRUE;
}

BOOL CPop::Statistics()
{
char buf [512];

wsprintf (buf, "STAT \r\n");
m_PopServer.Send(buf, strlen (buf));
if (CheckResponse(STAT_CHECK)==FALSE)
return FALSE;
else
return TRUE;
}

CString CPop::GetMsgContents()
{
return m_MsgContents;
}

int CPop::GetNumberOfMails()
{
return m_NumberMail;
}

int CPop::GetTotalMailSize()
{
return m_TotalSize;
}

BOOL CPop::Connect()
{
Connect(m_Host, m_User, m_Password);
return TRUE;
}

void CPop::SetHost(CString & Host)
{
m_Host = Host;
}

CString CPop::GetHost()
{
return m_Host;
}

void CPop::SetUser(CString & User)
{
m_User = User;
}

CString CPop::GetUser()
{
return m_User;
}

void CPop::SetPassword(CString & Password)
{
m_Password = Password;
}

CString CPop::GetPassword()
{
return m_Password;
}

BOOL CPop::CheckResponse(int ResponseType)
{
char buf [1000];

for (int i=0;i<512;i++)
buf[i]=’\0′;

m_PopServer.Receive(buf, sizeof(buf));

switch (ResponseType)
{
case CONNECTION_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Bad Connection");
return FALSE;
}
break;

case USER_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Bad User Name");
return FALSE;
}
break;
case PASSWORD_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Bad Password Name");
return FALSE;
}
break;
case QUIT_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Error occured during QUIT");
return FALSE;
}
break;
case DELETE_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Error occured during DELE");
return FALSE;
}
break;
case RSET_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Error occured during RSET");
return FALSE;
}
break;
case STAT_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Error occured during STAT");
return FALSE;
}
else
{
BOOL EmailNumber = TRUE;
for (char *p = buf; *p != ‘\0′; p++)
{
if (*p == ‘\t’ || *p == ‘ ‘)
{
if(EmailNumber == TRUE)
{
m_NumberMail = atoi(p);
EmailNumber = FALSE;
}
else
{
m_TotalSize = atoi(p);
return TRUE;
}
}
}

}
break;
case NOOP_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Error occured during NOOP");
return FALSE;
}
break;

case LIST_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Error occured during LIST");
return FALSE;
}
else
{
m_PopServer.Receive(buf, sizeof(buf));

for (char *p = buf; *p != ‘.’; p++)
if (*p == ‘\t’ || *p == ‘ ‘)
m_SizeOfMsg.Add(atoi(p));
}
break;
case RETR_CHECK:
if (strnicmp(buf,"-ERR", 4) == 0)
{
m_ErrorMessage = _T("Error occured during RETR");
return FALSE;
}
else
{
char temp[9000];
m_PopServer.Receive(temp, sizeof(temp));
m_MsgContents = temp;
}
break;
}
return TRUE;
}

CString CPop::GetErrorMessage()
{
return m_ErrorMessage;
}

BOOL CPop::List()
{
char buf [512];

wsprintf (buf, "LIST \r\n");
m_PopServer.Send(buf, strlen (buf));
if (CheckResponse(LIST_CHECK)==FALSE)
return FALSE;
else
return TRUE;
}

原文章发布于 2000.5.25 by Jephe Wu

  1. SMTP是工作在两种情况下:一是电子邮件从客户机传输到服务器;二是从某一个服务器传输到另一个服务器
  2. SMTP是个请求/响应协议,命令和响应都是基于ASCII文本,并以CR和LF符结束。响应包括一个表示返回状态的三位数字代码
  3. SMTP在TCP协议25号端口监听连接请求
  4. 连接和发送过程:
    • a.建立TCP连接
    • b.客户端发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令 服务器端正希望以OK作为响应,表明准备接收
    • c.客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行 服务器端则表示是否愿意为收件人接受邮件
    • d.协商结束,发送邮件,用命令DATA发送
    • e. 以.表示结束输入内容一起发送出去
    • f.结束此次发送,用QUIT命令退出。
  5. 另外两个命令: VRFY—用于验证给定的用户邮箱是否存在,以及接收关于该用户的详细信息。 EXPN—用于扩充邮件列表。
  6. 邮件路由过程: SMTP服务器基于‘域名服务DNS中计划收件人的域名来路由电子邮件。SMTP服务器基于DNS中的MX记录 来路由电子邮件,MX记录注册了域名和相关的SMTP中继主机,属于该域的电子邮件都应向该主机发送。 若SMTP服务器 mail.abc.com 收到一封信要发到 shuser@sh.abc.com:
    • a.Sendmail请求DNS给出主机sh.abc.com的CNAME记录,如有,假若CNAME到shmail.abc.com,则再次请求shmail.abc.com的CNAME记录,直到没有为止
    • b.假定被CNAME到 shmail.abc.com , 然后 sendmail 请求 @abc.com 域的DNS给出 shmail.abc.com 的MX记录, shmail MX 5 shmail.abc.com 10 shmail2.abc.com
    • c. Sendmail 最后请求 DNS 给出 shmail.abc.com 的 A 记录,即 IP 地址,若返回值为1.2.3.4
    • d. Sendmail 与 1.2.3.4 连接,传送这封给 shuser@sh.abc.com 的信到 1.2.3.4 这台服务器的SMTP后台程序
  7. SMTP基本命令集:

    命令 描述
    ——————————
    HELO 向服务器标识用户身份
    发送者能欺骗,说谎,但一般情况下服务器都能检测到。
    MAIL 初始化邮件传输
    mail from:
    RCPT 标识单个的邮件接收人;常在MAIL命令后面可有多个rcpt to:
    DATA 在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以.结束。
    VRFY 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令
    EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用
    HELP 查询服务器支持什么命令
    NOOP 无操作,服务器应响应OK
    QUIT 结束会话
    RSET 重置会话,当前传输被取消
    ——————————–

  8. MAIL FROM 命令中指定的地址是称作 envelope from 地址,不需要和发送者自己的地址是一致的。
    RCPT TO 与之等同,指明的接收者地址称为envelope to地址,而与实际的to:行是什么无关。
  9. 为什么没有RCPT CC和RCPT BCC:?
    所有的接收者协商都通过RCPT TO命令来实现,如果是BCC,则协商发送后在对方接收时被删掉信封接收者
  10. 邮件被分为信封部分,信头部分和信体部分
    envelope from, envelope to 与message from:, message to:完全不相干。
    evnelope是由服务器主机间SMTP后台提供的,而message from/to是由用户提供的。有无冒号也是区别。

  11. 怎样由信封部分检查是否一封信是否是伪造的?
    • a. received行的关联性。
      现在的SMTP邮件传输系统,在信封部分除了两端的内部主机处理的之个,考虑两个公司防火墙之间
      的部分,若两台防火墙机器分别为A和B,但接收者检查信封received:行时发现经过了C.则是伪造的。
    • b. received:行中的主机和IP地址对是否对应如:
      Receibed: from galangal.org (turmeric.com [104.128.23.115] by mail .bieberdorf.edu….
    • c. 被人手动添加在最后面的received行:
      Received: from galangal.org ([104.128.23.115]) by mail .bieberdorf.edu (8.8.5)
      Received: from lemongrass.org by galangal.org (8.7.3)
      Received: from graprao.com by lemongrass.org (8.6.4)

原文章发布于 2000.5.22 by Jephe Wu

  1. POP适用于C/S结构的脱机模型的电子邮件协议,目前已发展到第三版,称POP3。脱机模型即不能在线操作,不像IMAP4(netscape支持IMAP4)
  2. 当客户机与服务器连接并查询新电子邮件时,被该客户机指定的所有将被下载的邮件都将被程序下载到客户机,下载后,电子邮件客户机就可以删除或修改任意邮件,而无需与电子邮件服务器进一步交互。
  3. POP3客户向POP3服务器发送命令并等待响应,POP3命令采用命令行形式,用ASCII码表示服务器响应是由一个单独的命令行组成,或多个命令行组成,响应第一行以ASCII文本+OK或-ERR指出相应的操作状态是成功还是失败

  4. POP适用于C/S结构的脱机模型的电子邮件协议,目前已发展到第三版,称POP3。脱机模型即不能在线操作,不像IMAP4(netscape支持IMAP4)
  5. 当客户机与服务器连接并查询新电子邮件时,被该客户机指定的所有将被下载的邮件都将被程序下载到客户机,下载后,电子邮件客户机就可以删除或修改任意邮件,而无需与电子邮件服务器进一步交互。
  6. POP3客户向POP3服务器发送命令并等待响应,POP3命令采用命令行形式,用ASCII码表示服务器响应是由一个单独的命令行组成,或多个命令行组成,响应第一行以ASCII文本+OK或-ERR指出相应的操作状态是成功还是失败

  7. 在POP3协议中有三种状态,认可状态,处理状态,和更新状态。
    当客户机与服务器建立联系时,一旦客户机提供了自己身份并成功确认,即由认可状态转入处理状态,在完成相应的操作后客户机发出quit命令,则进入更新状态,更新之后最后重返认可状态。如下图

    等待连接        身份确认         quit命令
      ——  |认可|————— |处理|——————|更新|
             |__________________________________|
                      重返认可状态

  8. 认可状态的命令语句

    一般情况下,大多数现有的POP3客户与服务器执行采用ASCII明文发送用户名和口令,在认可状态下等待客户连接的情况下,客户发出连接,并由命令user/pass对在网络上发送明文用户名和口令给服务器进行身份确认。一旦确认成功,便转入处理状态。

    为了避免发送明文口令的问题,有一种新的认证方法,命令为APOP,使用APOP,口令在传输之前被加密。

    当第一次与服务器连接时,POP3服务器向客户机发送一个ASCII码问候,这个问候由一串字符组成。客户机是唯一的,与当时的时间有关,然后,客户机把它的纯文本口令附加到从服务器接收到的字符串之后, 然后计算出结果字符串的MD5单出函数消息摘要,客户机把用户名与MD5消息摘要作为APOP命令的参数一起发送出去。

    目前,大多数windows上的邮件客户软件不支持APOP命令,qpopper支持。

  9. POP3命令码如下:

    命令 参数 状态 描述
    ——————————————
    USER username 认可 此命令与下面的pass命令若成功,将导致状态转换
    PASS password 认可
    APOP Name,Digest 认可 Digest是MD5消息摘要
    ——————————————
    STAT None 处理 请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数
    UIDL [Msg#] 处理 返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的
    LIST [Msg#] 处理 返回邮件数量和每个邮件的大小
    RETR [Msg#] 处理 返回由参数标识的邮件的全部文本
    DELE [Msg#] 处理 服务器将由参数标识的邮件标记为删除,由quit命令执行
    RSET None 处理 服务器将重置所有标记为删除的邮件,用于撤消DELE命令
    TOP [Msg#] 处理 服务器将返回由参数标识的邮件前n行内容,n必须是正整数
    NOOP None 处理 服务器返回一个肯定的响应
    ——————————————
    QUIT None 更新

    a.客户机希望结束这次会话
    b.如果服务器处于‘处理’状态,那么将进入‘更新’状态以删除任何标记为删除的邮件
    c.导致由处理状态到更新状态,又重返认可状态的转变
    d.如果这个命令发出时服务器处于‘认可’状态,则结束会话,不进行‘更新’状态。

  10. POP3协议在TCP/110端口上等待客户连接请求。

  11. 若密码为明文,我如何监听?
    下面的命令在服务器运行后在屏幕上显示POP3连接及命令发送的过程:

    #sniffit -a -A. -p 110 -b -s 192.169.11.12


    note: 192.168.11.12是客户机IP地址
    你需要事先安装sniffit这个端口监听程序

  12. 考虑这种情况,若客户在收取邮件时,假定为15封信等待接收,但由于线路问题,收到第10封时断线了,为什么下次收时仍然从第一封开始,也即为什么前10封没有被从服务器上删除掉?

    任何邮件的删除都必须在quit命令发出后对已标记为删除的邮件执行删除操作,由于中途断线,仍处于处理状态,没有机会执行quit命令以进行状态转换。

  13. pop3 session is locked by another session, please wait 10 minutes then try again.

    由于非正常操作引起POP3程序内部机制锁住该次会话。

  14. Foxmail与OE(outlook express)的处理机制的不同。

    • a. 假定服务器上有三封邮件等待客户机接收。用foxmail与OE的不同之处在于foxmail每收一封标记删除一封,而OE则等全部接收完后再全部标记为删除最后执行quit命令。
      Foxmail OE ——————————- retr 1 retr 1 dele 1 retr 2 retr 2 retr 3 dele 2 dele 1 retr 3 dele 2 dele 3 dele 3 quit quit

    • b.Foxmail的远程邮件管理是非常优秀的管理工具,假定服务器上有三封信,对第一封,我们不想接收,而想从服务器直接删除;对第二封,想接收但不删除,对第三封,这一次不想接收,分别标记后最后foxmail发出的命令是

      dele 1
      retr 2
      quit


    • c.若没有foxmail,正好有几封很大的信堵住了,我不想接收,想直接删除它,或者想查看这两封是什么标题?

      直接在windows的DOS窗口下用命令行操作,如:

      # telnet my.isp.net 110
      user ‘username’
      pass ‘password’
      list
      dele 3
      dele 5
      quit

2005年07月15日

Description:

When writing CGI scripts which suck in textual content from users (such as discussion threads, for example), it’s often useful to be able to detect and/or remove HTML tags in user-submitted content. This regular expression, documented in perlfaq6, is relatively effective at getting rid of HTML.

Usage: Text Source

while(<>) {
  s/<(?:[^>'"]*|(['"]).*?\1)*>//gs;
}

The license for this recipe is available here.