使用C#进行SMTP协议客户端开发心得--读取服务器应答篇

smtp|服务器|客户端|心得

以TcpClient连接方式为例,首先取得服务器发回的数据流。

NetworkStream streamAccount=tcpClient.GetStream();

当我们对smtp服务器发送请求,例如连接,传送用户名,密码后,服务器会返回应答数据流。

我们必须对服务器返回数据流进行读取,这一步我经历了3次改动。

最开始的程序是按照《Visaul C#.NET网络核心编程》这本书上的例子来写的:

private string ReadFromNetStream(ref NetworkStream NetStream)
{
byte[] by=new byte[512];
NetStream.Read(by,0,by.Length);
string read=System.Text.Encoding.ASCII.GetString(by);
return read;
}

这种方式其实就是把读到的数据流全部变成字符串形式,但是实际网络传输中,smtp服务器发回的其实不一定全部是有效的命令,命令都是以<CRLF>(回车加换行)结束的。因此这样的读取方式存在问题。

修改以后的代码如下:

private string ReadFromNetStream(ref NetworkStream NetStream,string strEndFlag)
{
string ResultData = "";
byte[] ubBuff=new byte[1024];
try
{
while(true)
{
int nCount = NetStream.Read(ubBuff,0,ubBuff.Length);
if( nCount > 0 )
{
ResultData += Encoding.ASCII.GetString( ubBuff, 0, nCount);
}

if( ResultData.EndsWith(strEndFlag) )
{
break;
}

if( nCount == 0 )
{
throw new System.Exception("timeout");
}
}
}
catch(System.Exception se)
{
throw se;
MessageBox.Show(se.ToString());
return "";
}
return ResultData;
}

这样一来,就可以截取出以回车换行结束的命令。但是这样做还是不够正确的,因为smtp服务器在某些情况下会发回一些欢迎信息之类的东西,它们也是以<CRLF>(回车加换行)结束的,我们用上边的程序得到的很有可能不是我们实际想要得到的正确命令。

于是我只有再次修改程序如下:

/**
*
* 读取服务器的返回信息流
*
*/
public string ReadFromNetStream(ref NetworkStream NetStream)
{

if( NetStream == null )
return "";

String ResultData = "";
try
{
while(true)
{
string LineData = ReadLineStr(NetStream);
if( null != LineData
&& LineData.Length > 4)
{
if(LineData.Substring(3,1).CompareTo(" ") != 0)
{
ResultData += LineData + "\r\n";
continue;
}
else
{
ResultData += LineData;
break;
}
}
else
{
ResultData += LineData;
break;
}
}
}
catch(Exception e)
{
throw e;
}

return ResultData;
}

/**
*
* 逐行读取服务器的返回信息
*
*/
public byte[] readLine(NetworkStream m_StrmSource)
{
ArrayList lineBuf = new ArrayList();
byte prevByte = 0;

int currByteInt = m_StrmSource.ReadByte();
while(currByteInt > -1)
{
lineBuf.Add((byte)currByteInt);

if((prevByte == (byte)'\r' && (byte)currByteInt == (byte)'\n'))
{
byte[] retVal = new byte[lineBuf.Count-2];
lineBuf.CopyTo(0,retVal,0,lineBuf.Count-2);

return retVal;
}

prevByte = (byte)currByteInt;

currByteInt = m_StrmSource.ReadByte();
}

if(lineBuf.Count > 0)
{
byte[] retVal = new byte[lineBuf.Count];
lineBuf.CopyTo(0,retVal,0,lineBuf.Count);

return retVal;
}

return null;
}

/**
*
* 将服务器的返回信息逐行转换成字符串
*
*/
public string ReadLineStr(NetworkStream myStream)
{
byte[] b = readLine(myStream);
if( null == b)
{
return null;
}
else
{
return System.Text.Encoding.ASCII.GetString( b );
}
}

这样一来,我们就能读到那些以3位应答码开始,加一个空格,然后是一些发回的数据流,结尾是回车加换行的正确命令格式。

时间: 2024-04-20 05:54:30

使用C#进行SMTP协议客户端开发心得--读取服务器应答篇的相关文章

使用C#进行SMTP协议客户端开发心得--连接篇

smtp|客户端|心得 一. 关于与服务器的连接 与smtp服务器的连接一般采用两种方式: 第一种: 当服务器地址是字符串型的,例如"smtp.tom.com","211.128.11.25"这样的形式时,我们可以用TcpClient类建立连接. tcpClient = new TcpClient (smtpServer, smtpPort); 隶属命名空间: System.Net.Sockets.TcpClient 为使 TcpClient 连接并交换数据,使用

MapInfo开发心得——多地图关联篇

多个窗体(MDI)同时展示,并相互操作这并不困难,小弟在这介绍一下由MapInfo中MapControl组成的多窗体关联处理. 首先看看效果: 开发心得--多地图关联篇-mapinfo二次开发"> 以上多关联地图窗体实现了:在同一个窗体中加载多个(最多4个)地图,地图的拖拽.缩放操作可相互关联,每个地图上各个数据都可以完全不相同! 现在我来说一下实现过程: 首先要在同一个窗体中加载多个地图,我采用了UserControl来做: public partial class ViewMap :S

开放源码-SMTP发信客户端 for Java

smtp|客户端 //------------------------------------------------------------------// \\\|///// \\ -^- //// ( @ @ )// +----------------------oOOo-(_)-oOOo---------------------+//// FREE SOFTWARE WRITEN BY NAVY, COPYLEFT (C) 2002// SmtpClient Class 1.0 // U

关于SMTP协议发送邮件的总结

  最近在看一本书,是VC++网络编程,可以说那本书写的乱七八糟,我也晕头转向...  . 我写的大家可能有些看着抽象,捡着能看懂的看就行,我讲述的是SMTP的原理,而不是如何编程来实现,我纠结一天的感悟,希望对学习网络编程的朋友能有些帮助...   书上的SMTP小例子是写一个可以向  smtp.163.com邮件服务器邮件,于是我就跟着探索!!    SMTP是简单邮件传送协议,标准端口是25 ,SMTP也是TCP/IP族的成员,     其实一直不大理解 SMTP协议 FTP协议等等协议,

基于smtp协议的邮件系统(自己写的)

最近几天做好了应用[贱泰迪],其中有个意见反馈,发送邮件, 我知道可以调用系统发送邮件,但这种方法有个弊端,就是您的手机必须安装Mail的客户端, 因此我想不用系统发送邮件这种方式,能不能向任意邮箱发送邮件呢?给我自己丢下了一个命题. 于是我调查,发现SMTP发送email 无需系统支持,无需配置, 经过多次尝试,多次失败,终于完成了此项功能. 先来看应用[贱泰迪]的效果, 填写您的邮箱.密码等,我就能收到您的反馈意见,是不是很方便呢, 更多的效果,您可以下载贱泰迪(http://down.mu

JavaMail学习笔记(三)、使用SMTP协议发送电子邮件(全)

package org.yangxin.study.jm; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.

关于mapi、pop3协议、smtp协议的问题!请高手指点!!!

问题描述 1.请问MAPI是邮件协议还是函数接口,如果是协议的话能抓包看见吗?2.如果它是协议如何设置exchange服务器我才能抓到数据包?3.mapi和pop3协议,smtp协议有什么关系可以接发邮件不用pop3和smtp吗?4.MAPI可以优化吗?应该怎么优化? 解决方案 解决方案二:1.MAPI接口是由微软公司提供的一系列供使用者开发Mail.Scheduling.bulletinboard.communication程序的编程接口.2.3.有个imap协议,与pop3类似,也是收邮件用

RHCE 系列(九):如何使用无客户端配置 Postfix 邮件服务器(SMTP)

RHCE 系列(九):如何使用无客户端配置 Postfix 邮件服务器(SMTP) 尽管现在有很多在线联系方式,电子邮件仍然是一个人传递信息给远在世界尽头或办公室里坐在我们旁边的另一个人的有效方式. 下面的图描述了电子邮件从发送者发出直到信息到达接收者收件箱的传递过程. 电子邮件如何工作 要实现这一切,背后发生了好多事情.为了使电子邮件信息从一个客户端应用程序(例如 Thunderbird.Outlook,或者 web 邮件服务,例如 Gmail 或 Yahoo 邮件)投递到一个邮件服务器,并从

SD卡驱动开发心得体会

最近在负责SD卡驱动的开发移植工作,支持vfat文件系统,现在谈一下开发心得吧!         SD卡高度集成闪存,具备串行和随机存取能力.可以通过专用优化速度的串行接口访问,数据传输可靠.接口允许几个卡垛叠,通过他们的外部连接.接口完全符合最新的消费者标准,叫做SD卡系统标准,由SD卡系统规范定义. SD卡系统是一个新的大容量存储系统,基于半导体技术的变革.它的出现,提供了一个便宜的.结实的卡片式的存储媒介,为了消费多媒体应用.SD卡可以设计出便宜的播放器和驱动器而没有可移动的部分.一个低耗