资源描述
邮件服务器的实现
目 录
第一章 需求分析
1.1开发背景
1.2功能要求
第二章 系统总体分析
2.1 电子邮件介绍
2.2 总体设计方案及思路
2.2.1 电子邮件的发送程序
2.2.2 电子邮件的接收程序
2.3 模块分析
2.3.1 电子邮件发送程序的主要模块
2.3.2 电子邮件接收程序的主要模块
第三章 程序的测试(运行截图)
3.1添加“关于”标签的测试
3.2发送邮件的测试
3.3 收取邮件的测试
第四章 设计总结
4.1 课程小结
4.2 个人小结
附录 (源代码)
1 “关于”标签的程序代码
2 电子邮件发送程序的代码
3 附件的代码
3 电子邮件接受程序的代码
第一章、需求分析
1.1、开发背景
随着互联网的不断发展,越来越多的企业单位通过电子邮件来协同工作,打破时间与地域的限制,大大提高了工作效率。电子邮件已地经成为人们生活中不可缺少的一部分。
但是,当前流行的各大邮件客户端软件除了最主要的收发信件之外,功能越来越复杂,但是人们平常真正用到的功能很少,很多功能尤其对于那些计算机知识相对缺乏的人来说,更加显得太过于华丽而不实用。所以这次的VC++课程设计,我选择了制作一个操作简单,又可以实现最基本的电子邮件的收发功能的工具。
1.2、功能要求
①基本发送和接受邮件的功能。
②实现通信功能。
③具有简单、实用、易操作的图形界面。
④在以上基础上尽量实现发送附件的功能。
⑤程序还应可以判断整个过程是否能正常运行,如果不正常运行,必须给出错误信息。
第二章、系统总体分析
2.1、电子邮件介绍
电子邮件又称E-mai1,是—种用电子手段提供信息交换的通信方式。它是全球多种网络上使用最普遍的一项服务。这种非交互式的通信,加速了信息的交流及数据传送,它是—个简易、快速的方法。通过连接全世界的Internet,实现各类信号的传送、接收、存贮等处理,将邮件送到世界的各个角落。到目前为止,可以说电子邮件是Internet资源使用最多的一种服务,E-mai1不只局限于信件的传递,还可用来传递文件、声音及图形、图像等不同类型的信息。
电子邮件的处理由两大部分组成:电子邮件发送程序和电子邮件接收程序。电子邮件发送程序的发送方式有两种:第一种是本地计算机与用户所指定的发送邮件服务器连接,然后通过发送邮件服务器将邮件传递到接收邮件服务器,邮件中包含有信件的主题和内容等一系列信息;第二种是本地计算机直接与接收电子邮件的服务器相连,并将邮件送入收件者的邮箱中。电子邮件接收程序则只需要处理本地计算机与存放电子邮件的服务器相连接,并通过帐号和口令从服务器中获取电子邮件,邮件中包含有信件的主题、内容和发送时间等。
2.2、总体设计方案及思路
(1)电子邮件的发送程序
发送邮件的程序必须能够做3件事情: ①与接收电子邮件的服务器相连接; ②将相关的信息送入收件人的信箱;
③程序还应可以判断整个过程是否能正常运行,如果不正常运行,必须给出错误信息。
一般情况下,在VC++中,电子邮件程序的编写是利用Windows自带的MAPI以及相关的通信协议SMPT/POP3等来实现的。但是要利用MAPI和通信协议实现一个功能强大的电子邮件管理程序,需要很强的相关专业知识。随着现代软件业的发展,软件厂商提供了方便、简易,与服务器无关且稳定的电子邮件处理组件,使我们可以在程序开发语言中调用这些组件,利用很简单的语言实现功能强大的程序。JMail组件就是一个很好用的电子邮件程序开发第三方组件。所以这次的课程设计我选择了JMail组件。
JMail组件中包含许多实现电子邮件处理的属性和方法。只需要在VC++代码中创建一个JMail组件的对象,调用其中的某些功能,就能很快完成程序的开发。JMail常用的发送邮件的基本属性和方法如表1所示。
表1 JMail常用发送邮件的基本属性和方法
由于JMail是第三方组件,因此VC++程序要想调用JMail对象,就必须先下载JMail动态链接库,并在本机中进行注册。具体操作方法如下:打开运行对话框,输入cmd,打开命令提示符编辑器,输入如下指令即可注册成功:(JMail组件的安装路径)regsvr32 jmail.dll
(2)电子邮件的接收程序
接收邮件的程序必须能够做三件事:
①与存放电子邮件的服务器相连接;
②读取相关的信件信息,并存放与本地计算机中;
③程序还将判断整个过程是否能正常运行,如果不正常运行,必须给出错误信息。
与电子邮件发送程序的编写相同,我还是采取VC++语言和JMail组件相结合的方法来实现邮件的收取。JMail常用的接收邮件的基本属性和方法如表2所示。
表2 JMail常用接收信件的基本属性和方法
2.3、模块分析
电子子邮件接受方式程序主要由以下两个大的模块构成:发送邮件模块和收取邮件模块。其功能模块如图1所示:
图1 电子邮件功能模块图
(1)电子邮件发送程序的主要模块
电子邮件发送程序主要由以下几个模块组成:
①邮件服务器:用于填写收件人的邮箱服务器(可以不填);
②收件人信箱:用于填写收件人的邮箱名;
③发件人信箱:用于填写发件人的邮箱名;
④主题:用于填写信件主题;
⑤正文:用于写入信件正文;
⑥退出:用于退出发件程序;
⑦发送:用于发送邮件;
⑧关于:用于显示软件开发的相关信息。
⑨附件:可以手动添加附件并完成发送(该功能正在进一步完善中)。
(⑧⑨为本小组另行添加的功能)
(2)电子邮件接收程序的主要模块
电子邮件接收程序主要由以下几个模块组成:
①邮件服务器:用于填写需要收取信件信箱的服务器;
②帐号:用于填写需要收取信件的邮箱帐号;
③口令:用于填写需要收取信件的邮箱密码;
④邮件列表:显示邮箱中所有邮件的列表;
⑤正文:当选中邮件列表中任一邮件时,显示该封信件的具体内容;
⑥退出:用于退出接收邮件程序;
⑦收取:用于收取信件。
第三章、程序测试(运行截图)
3.1、添加“关于”标签的测试
在原设计的基础上我添加了一个“关于”的标签,点击该按钮会弹出一个小的对话框,其中的内容包括本小组的成员、程序开发时间以及一些关于邮件方面的相关帮助信息。
3.2、发送邮件的测试
图3 邮件发送主界面(不带附件)
图4 发送邮件程序主界面(加载附件)
图5 发送邮件程序主界面(带附件)
3.3、收取邮件的测试
图6 收取电子邮件程序主界面
第四章、设计总结
4.1、课程小结
在邮件发送程序中,用户可以利用SMPT服务器向朋友发送电子邮件,也可以直接尝试链接朋友的E-mail信箱所在的服务器。这次课程设计我所利用的JMail组件封装了很强的电子邮件处理功能,如附件传递、用户的跟踪服务、发布产品信息,以及电子报刊处理等功能。
在邮件接受程序中,用户可以向POP3服务器收取电子邮件。用户打开邮箱后,将利用JMail组件创建的对象指针遍历邮箱中的所有邮件,并将邮件信息下载存放于本地计算机中,利用List控件的扩展属性显示邮件的正文内容。
目前我所做的这个程序还不够完整,还存在着很多的不足和不完善的地方。归纳起来体现在以下几个方面:
①软件的功能趋于简单,真正的邮件收发工具软件包括很多方面的信息,而不仅仅局限于发送邮件和收取邮件。真正的邮件服务软件还包括邮件导入、邮件导出、文本编辑(查找与撤消)、通讯簿、通讯规则等等功能。
②软件的图形操作功能缺乏,目前系统中对邮件附件的添加、删除功能都没有图形快捷操作,只能通过改变源程序中的代码达到添加附件的目的。而且由于时间和知识的欠缺,整个系统的界面显得过于单调,缺乏动态显示效果。如果能结合其它界面美化工具,使得界面更人性化,那就更好了。
4.2、个人小结
经过不懈的努力,终于完成了这次的课程设计。其实在做这次VC++程序设计实验之前,我基本上没有真正意义上的接触过VC++程序案例的设计和开发,只是通过课堂了解了一些关于VC++的最基本的知识,所以这次实验是在边学习边实践的基础上完成的。由于知识的不足,做的结果自己不是很满意,与自己原来的设想也有些差距。但是我也从这两个星期的设计和制作过程中学到了很多知识,对自己以后的专业学习甚至将来的工作都有很大的帮助。
附录(源代码):
1、“关于”标签的程序代码
(1)往头文件StdAfx.h中添加下列代码:
#define CRLF "\x0d\x0a" //注意这两行必须添加
#define CRLF2 CRLF CRLF
(2)主要代码如下:
BOOL CAboutDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // TODO: Add extra initialization here m_strEditHelp= "相关帮助信息:" CRLF CRLF
" 一、 发送邮件服务器和发信人信箱有密切关系,假如你的信箱为loop@,则发送邮件服务器一般为:,当然这也不是绝对的,你可以到你的邮件相关网站查询。不知道服务器名的话也可以不填!"
CRLF
CRLF
" 二、 发信信箱格式比较灵活,如下两种格式均为合法的:1 在你的E-Mail首尾加小于大于符号:<loomman@> 2 直接填写你的E-Mail:loomman@ "CRLF
" 三、 接受信箱可以为多个,中间用分号;隔开,例如:Pookie<pookie@>;snuggles<snuggles@>;<loomman@> 某些信箱前面的部分字符串是收信人名称,例如上面的Pookie可以省略不写,例如下面一行和上面一行是等价的,它们都是可以接受的信箱输入格式。<pookie@>;<snuggles@>;<loomman@>"
CRLF
CRLF
" 四、 邮件主题,当然就是邮件的标题了,你可以随意输入自己喜爱的标题。" CRLF
CRLF
" 五、 邮件正文就是你要发给对方的信息。"
CRLF
CRLF
" 六、 最后不得不提一下,由于当今好多发送邮件服务器都要求身份验证,也就是需要提供的你的信箱密码,鉴于技术问题,这类信箱本程序暂时不支持。"
CRLF
CRLF
" ………………" CRLF
" 2007年7月"
CRLF
;
UpdateData(FALSE); // Update the Dialog
} return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE
2、发送邮件程序代码:
(1)往头文件StdAfx.h中添加JMail对象的声明,这样才能在整个程序中应用JMail对象.代码如下:
#import "C:\jmail\jmail.dll" //显示指定JMail动态链接库
using namespace jmail; //定义程序中JMail对象的名称
(2)头文件MailServer.h,利用ClassWizard类项导添加退出应用程序的函数ExitInstnace().源代码如下:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMailServerApp) public: virtual BOOL InitInstance(); virtual int ExitInstance(); //}}AFX_VIRTUAL
(3)源文件MailServer.cpp,类CMailServerApp的实现文件.
1)由于程序中应用了JMail组件,因此必须在InitInstance()函数中添加如下代码,进行应用程序的初始化.
BOOL CMailServerApp::InitInstance()
{
AfxEnableControlContainer(); ::CoInitialize(NULL);
// Call this when using MFC in a shared DLL #ifdef _AFXDLL Enable3dControls();
„„
}
2)应用程序时,在ExitInstance()函数中添加释放各变量的代码.
//应用程序退出时
int CMailServerApp::ExitInstance()
{
}
(4)MailServerDlg.h中,CMailServerDlg类的接口.
1)在头文件MailServerDlg.h中,添加各控件的控件变量,如下表所示.
// TODO: Add your specialized code here and/or call the base class return CWinApp::ExitInstance(); ::CoUninitialize();
Protected:
//{{AFX_MSG(CMailServerDlg)
„„
Afx_msg void OnSend();
//}}AFX_MSG
„„
3)源文件MailServerDlg.cpp,类CMailServerDlg的实现文件.打开MailServerDlg.cpp文件,添加发送邮件函数OnSend()的代码如下:
//发送邮件程序
void CMailServerDlg::OnSend()
{
// TODO: Add your control notification handler code here UpdateData(); //获取Edit控件中的字符串 m_strmailserver.TrimLeft();
m_strmailserver.TrimRight();
m_strrecipients.TrimLeft();
m_strrecipients.TrimRight();
m_strsender.TrimLeft();
m_strsender.TrimRight();
//判断Edit控件中的字符串是否有效
if(m_strrecipients.GetLength()<3)
{ } if (m_strsender.GetLength()<=0) { AfxMessageBox("请填写发件人邮箱"); } return; AfxMessageBox("请填写正确的收件人信箱"); return; //发送邮件过程 try { //创建一个JMail对象,这样便可以利用其内容封装的基本属性和方法 jmail::IMessagePtr pMessage("JMail.Message"); //发件人邮箱 pMessage->From=(LPCTSTR) m_strsender; //发件人姓名 pMessage->FromName="我的名字"; //添加收件人 pMessage->AddRecipient((LPCTSTR)m_strrecipients,"",""); //优先级设置,1~5逐次降低,3为中级 pMessage->Priority=3; //编码方式设置,默认是iso-8859-1 pMessage->Charset = "GB2312"; //主题 pMessage->Subject = (LPCTSTR) m_strsubject; //正文 pMessage->Body = (LPCTSTR) m_strbody; //开始发送 pMessage->Send((LPCTSTR) m_strmailserver,VARIANT_FALSE);
pMessage.Release();
AfxMessageBox("发送成功!");
} //捕捉异常 catch (_com_error e) { CString strErr;
strErr.Format("错误信息: %s\r\n 错误描述: %s ", (LPCTSTR)e.ErrorMessage() , (LPCTSTR)e.Description());
AfxMessageBox(strErr);
}
}
3、附件实现的代码:
附件发送的实现;
(1)首先在CMailServerDld类中定义几个对象。
public:
CString str;
CString tr;
BOOL strbool;
_bstr_t bstr;
(2)加载文件:
void CMailServerDlg::OnBtAddfile()
{
// TODO: Add your control notification handler code here CFileDialog cg(TRUE);
if(cg.DoModal()==IDOK) strbool=true;
else strbool=false;
cg.DoModal();
str=cg.GetPathName();
MessageBox(str);
}
(3)发送附件:
bstr=str.AllocSysString(); //CString类型转换成_bstr_t 类型
if(strbool==true) //判断有没有打开附件 {
_bstr_t bstrCID = pMessage->AddAttachment( bstr, VARIANT_TRUE, "");
//开始发送(带附件)
pMessage->Send((LPCTSTR) m_strmailserver,VARIANT_FALSE);
pMessage.Release();
AfxMessageBox("发送成功(带附件)!"); } else {
//开始发送(不带附件)
pMessage->Send((LPCTSTR) m_strmailserver,VARIANT_FALSE);
pMessage.Release();
AfxMessageBox("发送成功(不带附件)!");
}
//捕捉异常
catch (_com_error e) { CString strErr; strErr.Format("错误信息: %s\r\n 错误描述: %s ", (LPCTSTR)e.ErrorMessage() ,
(LPCTSTR)e.Description());
AfxMessageBox(strErr);
}
4、接受邮件程序代码:
(1)往头文件StdAfx.h中添加JMail对象的声明,这样才能在整个程序中应用JMail对象.代码如下:
//显示指定JMail动态链接库
#import "C:\jmail\jmail.dll"
//定义程序中JMail对象的名称
using namespace jmail;
(2)头文件MailServer.h,利用ClassWizard类项导添加退出应用程序的函数ExitInstnace().源代码如下:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMailServerApp) public: virtual BOOL InitInstance(); virtual int ExitInstance(); //}}AFX_VIRTUAL
(3)源文件MailRecieve.cpp,类CMailRecieveApp的实现文件.
1)由于程序中应用了JMail组件,因此必须在InitInstance()函数中添加如下代码,进行应用程序的初始化.
BOOL CMailRevieveApp::InitInstance()
{
AfxEnableControlContainer();
::CoInitialize(NULL);
// Call this when using MFC in a shared DLL #ifdef _AFXDLL Enable3dControls();
„„
}
2)应用程序时,在ExitInstance()函数中添加释放各变量的代码.
//应用程序退出时
int CMailRecieveApp::ExitInstance()
{
// TODO: Add your specialized code here and/or call the base class
} return CWinApp::ExitInstance(); ::CoUninitialize();
(4)MailRecieveDlg.h中,CMailRecieveDlg类的接口
LVN_ITEMCHANGE事件函数.代码如下:
Protected:
//{{AFX_MSG(CMailServerDlg)
„„
Afx_msg void OnRecieve();
afx_msg void OnShowBody(NMHDR* Pnmhdr,lresult* pResult);
//}}AFX_MSG
„„ 利用ClassWizard添加IDOK控件的ON_BN_CLICKED事件函数,添加List控件的
3)源文件MailRecieverDlg.cpp,类CMailRecieveDlg的实现文件.向MailServerDlg.cpp文件中添加初始化对话框函数OnInitDialog()的代码、OnRecieve()的代码和显示邮件正文函数OnShowBody()的代码:
BOOL CMailRecieveDlg::OnInitDialog()
{
„„
// TODO: Add extra initialization here
//初始化对话框的函数
//升级列表控件 ::SendMessage(m_ctlmessagelist.m_hWnd,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT); //显示控件列表 m_ctlmessagelist.InsertColumn(0,"发件人",LVCFMT_LEFT,120); m_ctlmessagelist.InsertColumn(1,"主题",LVCFMT_LEFT,350);
m_ctlmessagelist.InsertColumn(2,"日期",LVCFMT_LEFT,100);
return TRUE; // return TRUE unless you set the focus to a control }:
//接收邮件函数
void CMailRecieveDlg::OnRecieve()
{
// TODO: Add your control notification handler code here
//接受邮件的函数
UpdateData();
//格式化Edit控件中的字符串
m_strmailserver.TrimLeft();
m_strmailserver.TrimRight();
m_struserid.TrimLeft();
m_struserid.TrimRight();
m_strpassword.TrimLeft();
m_strpassword.TrimRight();
//判断帐号口令是否存在
if(m_strmailserver.GetLength()<=0)
{
AfxMessageBox("邮件服务器不能为空");
return;
}
if(m_struserid.GetLength()<=0)
{
AfxMessageBox("帐号不能为空");
return;
}
//清空List控件列表
m_ctlmessagelist.DeleteAllItems();
//清空存放邮件正文的数组
m_strBodyArray.RemoveAll();
//接受邮件
try
{
//创建新的JMail对象
jmail::IPOP3Ptr pPOP3("JMail.POP3");
jmail::IMessagePtr pMessages;
//设置链接服务器超时限制 30s
pPOP3->Timeout =30;
//链接邮件服务器,110为POP3默认端口号
pPOP3->Connect( (LPCTSTR)m_struserid , (LPCTSTR)m_strpassword (LPCTSTR)m_strmailserver,110);
//获取信件
pMessages=pPOP3->Messages;
//已下载的邮件的实际个数(因为第0个ITEM是未用的,所以减一)
long lCount =(pPOP3->Messages)->Count-1;
if(lCount == 0) ,
AfxMessageBox("信箱为空"); else { jmail::IMessagePtr pMessage; //遍历每 for(long i = 1 ; i<= lCount ; i++) { pMessage =(pPOP3->Messages)->Item[i]; //信件的具体信息 _bstr_t bstrFrom = pMessage->From; _bstr_t bstrBody = pMessage->Body; COleDateTime oleDate = pMessage->Date; //向List空间中添加信件信息
int nListItem = m_ctlmessagelist.InsertItem(i,(const char
char
char _bstr_t bstrSubject = pMessage->Subject; *)bstrFrom); m_ctlmessagelist.SetItem(nListItem,1,LVIF_TEXT,(const *)bstrSubject,0,0,0,NULL); m_ctlmessagelist.SetItem(nListItem,2,LVIF_TEXT,(const
*)oleDate.Format("%Y-%m-%d"),0,0,0,NULL);
//显示信件的主题文本
} } m_strBodyArray.Add((const char*)bstrBody); pMessage.Release(); //断开连接 pPOP3->Disconnect(); } //提示错误信息 catch(_com_error e)
{
CString strErr;
strErr.Format("错误信息:%s\r\n 错误描述:%s" , (LPCTSTR)e.ErrorMessage(),(LPCTSTR)e.Description());
}
void CMailRecieveDlg::OnShowBody(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; } AfxMessageBox(strErr);
// TODO: Add your control notification handler code here
//显示邮件正文内容
} //获取选定信件的指针 POSITION pos = m_ctlmessagelist.GetFirstSelectedItemPosition(); if(pos) { int nItem = m_ctlmessagelist.GetNextSelectedItem(pos); } //显示内容 m_strbody = m_strBodyArray.GetAt(nItem); UpdateData(FALSE); *pResult = 0;
展开阅读全文