关闭

Email协议小贴

标签: email服务器postscriptapplicationinternet邮件服务器
1741人阅读 评论(0) 收藏 举报

Email协议
SMTP协议:
1 信件体:在RFC822中,是一系列的文本行
2 信头:   结构较复杂,总的来说是由一些字段组成,这些字段为用户和程序提供了关于信件的信息,了解信头就是弄清楚信头的各个字段。每个信头字段由一行或多行组成,对于跨多行的字段,附加行以一个空格开始作为续行。
Field-name(字段名)由一系列可以打印的US-ASCII字符组成,除空格和":"外,大多数字段名称由一系列字母,数字,中间经常插入横线符。

步骤:
     1 客户端程序发送邮件到SMTP服务器
     2 SMTP服务器传递邮件到pop3接受服务器
     3 接受邮件客户端从pop3上接受
     (MPTP简单邮件传输协议,POP3邮局协议)
标准字段:
1 from:表述产生这个信件的人,通常含有一个信箱(From:XX@CC.com)
2 sender:用于指示信件发送者与信件创建者是否不同(From:XXX@CC.net and Sender:XXX@CC.net) 并不一  样
3 Reply-To:用于控制信件要回复的目的地
4 To:信件的主要收信人
5 Cc:信件的辅收信人
6 Bcc:密件抄送的缩写
7 Message-IDL用于一个信件的唯一标志,有SMTP服务器生成
8 Date含有电子邮件的创建日期和时间
9 Received:为信件的一个特定的邮件投递服务器记录
10重发字段(Resent-*)
11Subject用于描述信件的主题
12Comments用于吧一个注释添加到信件中
13扩展字段..(X-Loop ,X-Mailer)
MIME对信头字段的扩展
 MIME 对RFC822的字段补充了一些信头字段,这些字段通常是在发送电子邮件的软件在创建电子邮件时产生的,接受电子邮件的软件提取其中的字段得到有用的信息
MIME补充的信头字段:
MIME-Version字段用于标志使用的MIME版本号,这是为了将来增加版本号解决兼容的问题。该字段是MIME信件唯一必须要求出现的字段。
目前只有一个MIME版本在使用,一般加入一下字段:
MIME-Version: 1.0
Content-Type是MIME中的主要字段,描述特定MIME实体中包含的数据。
这个字段有3部分:前两部分组成媒体类型和1个可选分号分开的参数列表。如:
Content-Type:text/plain;charset="us-ascii"
其中text是媒体类型主类别,plain指媒体类型的附加层次类别。charset="us-ascii"是可选的参数列表。又如: Content-Type:text/html;charset=gb2312
指定媒体的主类型是text,但文本内容是HTML格式文件。使用字符集是GB2312。
 Content-Transfer-Encoding,许多数据格式可以包含在信件中允许的字符范围之外的字节值,而且含有超过允许长度的数据行。一些数据格式的定义甚至没有行的概念。Content-Transfer-Encoding字段解决这些问题.
该字段有5个值:7bit,8bit,binary,base64和quoted-printable.每个值都不区分大小写。符合MIME规范的邮件处理程序必须能对这些编码正确处理
(1)7bit特点:
    编码长度不超过998字节的数据,且该数据以Crlf结束的行组成 .为缺省编码,如果不提供Content-Transfer-Encoding字段,就认为是7bit编码
(2)8bit特点:
    与7bit一样但允许US-ASCII 0
(3)binary编码用于任意二进制8位数据,对行长度和允许的字符没有限制。在MIME信件实体里包含这种数据是不合法的,它仅仅是告诉指定数据的数据类型,而数据不是给随邮件作为邮件内容发送的。
(4)base64特点:
     把二进制数据编码成适合通过internet传送的格式,在处理二进制数据作为邮件实体内容发送时,这种编码方式应用的最为广泛
 在base64编码过程中要注意:
         1:编码后的文本每行的长度:邮件的文本行每行应该控制在76个字符以内,如果超过需插入Crlf(回车换行)。插入的Crlf不需要编码
         2填充字符
  (1)quoted-printable编码有文本组成的数据,在行超过80个字符的情况下很有用
  (2)x-uuencode 常用在MIME实体中进行标志
5 MIME 媒体类型
 Connect-Type是用于在信头中指定媒体类型的字段,是MIME对RFC822扩展的主要信头字段
 Connect-Type: 媒体类型主类别/媒体类型的附加层次类别+有可选分号分开的参数列表。
一共有8个顶层的媒体类型:Text,Image,Audio,Video,Application,Message和Multipart.这些主要类型为他们各自的数据提供了一个结构
(1)Text
 Text类型用于指示基于文本的内容。这里类别中任何子类型都不需要程序格式化数据而进行约定。参数有charset,用于指定Text所使用的字符集,缺省时为US-ASCII.如:
Content-Type:text/plain;charset=us-ascii与Content-Type:text/plain是一样的
Text的附加层次媒体类型还有:Plain, Enrich,Html等
   1 TEXT:
    text/plain 媒体类型标识有普通可打印字符组成,可以是US-ASCII,也可以是汉字,这些数据没有经过格式化,直接浏览阅读即可.
    text/enrich 为创建有对齐,颜色和字体变化功能的文本提供了一个简单的标记语言。
    text/Html
   2 Image,Audio和Video
    这几个媒体的主要类别是相当直观的,数据通常是二进制的,采用base64编码
    Content-Type:Image/jpeg
    Content-Transfer-Encoding:base64
   3 Application: 该媒体类别含有与特定应用文件格式有关的任何媒体类型。
    几种附加层次类别:
     octet-stream ,Content-Type:Application/actet-stream
       Application/actet-stream指示一个实体中含有任意数据,当内容未知或者对数据没有定义媒体类型时,通常使用它
     Postscript ,Content-Type:Application/Postscript
     Application/Postscript媒体类型用于标识一个实体的内容是Postscript代码。因为     Application/Postscript实体含有可执行代码,他的内容必须毫无损失的到达目的地,也许是这个原因,通常使用quoted-printable编码,是他不至于因为长度限制或在通过Internet网关时被破坏
    Message 这个媒体类型的主类别指定信体组成的实体
    RFC822,Content-Type:message/RFC822
    message/RFC822类型提供在一个信件中打包另外一个信件的简单方法。所有符合MIME的邮件处理程序都必须支持这种类型的分析
    Partial,Content-Type:message/Partial
    message/Partial媒体类型指定了一种方法,该方法把大的实体分成多个部件,每个部件可以分开传输在接受端组装,在发送和传输邮件的服务器之间有信件尺寸限制的情况下,这种方法可以传送比较大的信件
    External-body,content-type:message/External-body
    message/External-body表示实体含有的数据并不在信件内容里,而仅仅是描述了一种从外部取出数据的方式。
    Multipart,Content-Type:mulipart/mixed
     Multipart媒体类型的主类别表示多个实体打包到单个实体,多部件实体由一个可选的前导,一个或多个信件体部件(每个前面有一个边界行)和一个可选的结尾部件组成。边界行由两个横线后跟一个边界字符串组成。这个边界字符串由Content-Type字段中的参数boundary的值指定

SMTP会话:
特点:
    1 全过程发送文本完成,交互式请求应答模式
    2 命令是文本形式的命令
    3 服务器总返回一定的相应码,表示客户端的请求是否被正确的回答
    4 会话过程有一定的顺序
补充:
  1 Email通信是基于TCP/IP协议,要首先用WinSock建立和SMTP服务器的连接
  2 连接成功后,要进行会话,SMTP有其认识的一整套命令,当然是事先约定好的,SMTP协议的很重要的一    部分就是会话的标准命令
  3 不过骇心命令不多,甚至几个就能完成会话

一个简单的会话 例子:
   1:AfxSocketInit(NULL)
   2:m_Socket.Create()
   3:m_Socket.Connect(LPCSTR(temp),25)
   4:virtual void OnReceive(int nErrorCode);等待服务器回应接受m_Socket.Receive(sBuffer,sizeof    (sBuffer));
   5:发送m_Socket.Send("HELO smtp.sohu.com/r/n" ,len ) 返回4
   6:发送m_Socket.Send("MAIL FROM: mmnihao_@sohu.com/r/n" ,len ) 返回4
   7:发送m_Socket.Send("RCPT TO: mmnihao_@sohu.com/r/n" ,len ) 返回4
   8:发送m_Socket.Send("DATA/r/n" ,len ) 返回4 
   9:发送m_Socket.Send("text/r/n/r/n./r/n" ,len ) 返回4 (注意".")
   9:发送m_Socket.Send("QUIT/r/n" ,len ) 返回4   
   10 结束

程序:
  1定义一个CESocket类 继承于CSocket负责相应接受数据消息,CESocket初始化Init
  m_iCount 是一个命令发送的序号
//初始话
void CESocket::Init(CEmailSendDlg  *dlg)
{
 m_dlg=dlg;
 m_iCount=0;
}
CESocket接受数据相应函数OnReceive,调用主对话框的接受消息处理函数,同时增加m_iCount
//接受数据响应函数,调用主对话框的接受消息处理函数,同时增加m_iCount
void CESocket::OnReceive(int nErrorCode)
{

 m_dlg->ReceiveMessage(m_iCount);
  m_iCount++;
 CSocket::OnReceive(nErrorCode);
}


2:对话框的消息处理函数:
void CEmailSendDlg::OnSend()
{

 GetDlgItemText(IDC_SMTP_ADDRESS,  m_sSendString[0]);
 GetDlgItemText(IDC_FROM_ADDRESS,  m_sSendString[1]);
 GetDlgItemText(IDC_TO_ADDRESS,  m_sSendString[2]);

 m_sSendString[0].TrimLeft(" ");
 m_sSendString[0].TrimRight(" ");
 m_sSendString[1].TrimLeft(" ");
 m_sSendString[1].TrimRight(" ");
 m_sSendString[2].TrimLeft(" ");
 m_sSendString[2].TrimRight(" ");
 
 if(m_sSendString[0].IsEmpty())
 {
  AfxMessageBox("请输入SMTP服务器地址(IP)");
  return;
 }
 if(m_sSendString[1].IsEmpty())
 {
  AfxMessageBox("请输入你的EMail地址");
  return;
 }
 if(m_sSendString[2].IsEmpty())
 {
  AfxMessageBox("请输入收件人的EMail地址");
  return;
 }

 m_sSendString[0]="HELO "+m_sSendString[0]+"/r/n";
 m_sSendString[1]="MAIL FROM: "+m_sSendString[1]+"/r/n";
 m_sSendString[2]="RCPT TO: "+m_sSendString[2]+"/r/n";

 m_sSendString[3]="DATA/r/n";
 
 GetDlgItemText(IDC_EMAIL_CONTENT,m_sSendString[4]);
 m_sSendString[4]=m_sSendString[4]+"/r/n/r/n./r/n";
 
 m_sSendString[5]="QUIT/r/n";

 CString temp;
 GetDlgItemText(IDC_SMTP_ADDRESS,temp);

 if(m_Socket.Connect(LPCSTR(temp),25)==FALSE)
 {
 }
 m_sReceivedData="";
}
当客户端连接大SMTP服务器后,smtp会发送一段欢迎码然后客户端和服务器就可以按照SMTP命令进行会话
直到信件发送结束
void CEmailSendDlg::ReceiveMessage(int count)
{
 if(count>=6)
 {
  AfxMessageBox("Unknown Received Data");
  m_Socket.Close();
  return;
 }
 char sBuffer[255];
 int len=m_Socket.Receive(sBuffer,sizeof(sBuffer));
 sBuffer[len]=NULL;

 m_sReceivedData=m_sReceivedData+sBuffer;
 m_sReceivedData=m_sReceivedData+m_sSendString[count];

 m_Socket.Send(m_sSendString[count],m_sSendString[count].GetLength());

}

 


//----------------------------------------------
如何获取从发信服务器到网易MX服务器的SMTP会话样例?字体: 小 中 大
  利用telnet手工模拟一次smtp会话过程,能提供许多有用的信息,从而帮助我们迅速定位您的问题。下面这个手工smtp会话测试过程可以在多个操作系统下运行,包括Windows、Unix、和Linux。
  本帮助讲述了如果利用telnet来模拟一次完整的发信。请将您的整个会话过程复制下来,并发送给我们。
  2nn开头的返回码,表示会话是正常的。而5nn或者4nn开头的返回码则表示有错误发生。
  注意:本测试过程必须在发信服务器上进行。

  下面是具体步骤:
  1、打开一个命令窗口,键入:
  telnet mx.mail.126.split.netease.com 25
  这条命令将建立一个到我们126邮件服务器的连接。
  2、 键入:
  HELO yourdomain.com
  这里的yourdomain.com指您的域名。
  3、 键入:
  MAIL FROM:< you@yourdomain.com >(无需空格)
  这里的you@yourdomain.com指您们域的一个邮箱名。
  注意:邮箱名需要用<>括起来。
  4: 键入:
  RCPT TO:< postmaster >(无需空格)
  这将发信到我们的postmaster邮箱。
  注意:邮箱名需要用<>括起来。
  5: 键入:
  DATA
  6: 输入邮件的信头和正文。
  FROM:< you@yourdomain.com>(无需空格)
  TO:< postmaster>(无需空格)
  SUBJECT: yourdomain.com to netease

  Hi!
  It's from yourdomain.com. Just a test.
  Bye.
  7: 新起一个空行,键入:
  .
  然后按回车,这将结束整封信,并发送给服务器

    

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:215109次
    • 积分:2791
    • 等级:
    • 排名:第13256名
    • 原创:79篇
    • 转载:0篇
    • 译文:0篇
    • 评论:10条
    最新评论