步骤:
1 客户端程序发送邮件到SMTP服务器
2 SMTP服务器传递邮件到pop3接受服务器
3 接受邮件客户端从pop3上接受
(MPTP简单邮件传输协议,POP3邮局协议)
标准字段:
1 from:表述产生这个信件的人,通常含有一个信箱(From:[email protected])
2 sender:用于指示信件发送者与信件创建者是否不同(From:[email protected] and Sender:[email protected]) 并不一 样
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: [email protected]\r\n" ,len ) 返回4
7:发送m_Socket.Send("RCPT TO: [email protected]\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:< [email protected] >(无需空格)
这里的[email protected]指您们域的一个邮箱名。
注意:邮箱名需要用<>括起来。
4: 键入:
RCPT TO:< postmaster >(无需空格)
这将发信到我们的postmaster邮箱。
注意:邮箱名需要用<>括起来。
5: 键入:
DATA
6: 输入邮件的信头和正文。
FROM:< [email protected]>(无需空格)
TO:< postmaster>(无需空格)
SUBJECT: yourdomain.com to netease
Hi!
It's from yourdomain.com. Just a test.
Bye.
7: 新起一个空行,键入:
.
然后按回车,这将结束整封信,并发送给服务器