首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 图形图象-> 相关软件
用visual c++编写电子邮件程序_邮件服务器
作者:网友供稿 点击:0
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 
一、概述
本文主要讲述如何使用Visual C++用MAPI编写E-mail程序。MAPI是包含在Windows之中的,因此不需要安装其他额外的部件。MAPI有以下三种形式:

SMAPI,Simple MAPI,简单的MAPI

CMC,Common Messaging Calls,一般通讯调用

完整的MAPI
SMAPI和CMC都包含在完整的MAPI中,当用户想执行一些高级操作,比如编写自己的E-mail服务器的时候,必须使用完整的MAPI。本文主要阐述如何编写能够收发电子邮件的程序,因此使用SMAPI就足够了。

二、编写电子邮件程序
3-1 初始化MAPI

要使用MAPI,必须首先对它进行初始化。初始化包括以下三个步骤:

装载MAPI32.DLL动态链接库

找到想要调用的MAPI函数地址

登录到电子邮件对象
3-1-1 装载MAPI32.DLL

要装载MAPI,用户必须程序运行时动态的装载一个动态链接库。LoadLibrary函数提供了此功能,它定位一个动态链接库,并返回HINSTANCE局柄(需要保存该句柄)。

LoadLibrary的语法如下:
LoadLibrary ( lpLibFileName );
其中lpLibFileName为LPCTSTR结构变量,
是所要调用的库的路径和名称。

程序示例:
// 调用MAPI32.DLL并计算函数地址
HINSTANCE hInstMail;
hInstMail = ::LoadLibrary ( “MAPI32.DLL” );
if ( hInstMail == NULL )
{
// 错误处理
// 受篇幅限制,下面的错误处理部分省略
}

3-1-2 确定函数地址

由于MAPI32.DLL是被动态装载的,因此不知道所要调用的函数地址,也就不能一开始就调用它们,而要通过函数名获得函数的地址,并在动态链接库中查找每一个函数并核实。因此首先必须为这些函数声明指针

程序示例:
// 为MAPI32.DLL中的函数声明函数指针
ULONG (PASCAL *lpfnMAPISendMail) (LHANDLE lhSession,
ULONG ulUIParam, lpMapiMessage lpMessage,
FLAGS flFlags, ULONG ulReserved);
ULONG (PASCAL *lpfnMAPIResolveName) (LHANDLE lhSession,
ULONG ulUIParam, LPTSTR lpszName,
FLAGS ulFlags, ULONG ulReserved,
lpMapiRecipDesc FAR *lppRecip);
ULONG (FAR PASCAL *lpfnMAPILogon)(ULONG ulUIParam,
LPSTR lpszProfileName, LPSTR lpszPassword,
FLAGS flFlags, ULONG ulReserved,
LPLHANDLE lplhSession);
ULONG (FAR PASCAL *lpfnMAPILogoff)(LHANDLE lhSession,
ULONG ulUIParam, FLAGS flFlags,
ULONG ulReserved);
ULONG (FAR PASCAL *lpfnMAPIFreeBuffer)(LPVOID lpBuffer);
ULONG (FAR PASCAL *lpfnMAPIAddress)(LHANDLE lhSession,
ULONG ulUIParam, LPSTR lpszCaption,
ULONG nEditFields, LPSTR lpszLabels,
ULONG nRecips, lpMapiRecipDesc lpRecips,
FLAGS flFlags, ULONG ulReserved,
LPULONG lpnNewRecips,
lpMapiRecipDesc FAR *lppNewRecips);
ULONG (FAR PASCAL *lpfnMAPIFindNext)(LHANDLE lhSession,
ULONG ulUIParam, LPSTR lpszMessageType,
LPSTR lpszSeedMessageID, FLAGS flFlags,
ULONG ulReserved, LPSTR lpszMessageID);
ULONG (FAR PASCAL *lpfnMAPIReadMail)(LHANDLE lhSession,
ULONG ulUIParam, LPSTR lpszMessageID,
FLAGS flFlags, ULONG ulReserved,
lpMapiMessage FAR *lppMessage);

为了决定每一个函数的地址,必须为每一个函数调用GetProcAddress。

GetProcAddress的语法为:
GetProcAddress (hModule, lpProcName);
其中,hModule为HMODULE结构,是所调用DLL模块的句柄;
lpProcName为LPCSTR结构,是函数名称。

程序示例:
// 找到MAPI32.DLL函数的地址,并将它们保存在函数指针变量里
(FARPROC%26amp;) lpfnMAPISendMail = GetProcAddress(hInstMail,
“MAPISendMail”);
(FARPROC%26amp;) lpfnMAPIResolveName = GetProcAddress(
hInstMail, “MAPIResolveName”);
(FARPROC%26amp;) lpfnMAPILogon = GetProcAddress(hInstMail,
“MAPILogon”);
(FARPROC%26amp;) lpfnMAPILogoff = GetProcAddress(hInstMail,
“MAPILogoff”);
(FARPROC%26amp;) lpfnMAPIFreeBuffer = GetProcAddress(
hInstMail, “MAPIFreeBuffer”);
(FARPROC%26amp;) lpfnMAPIAddress = GetProcAddress(hInstMail,
“MAPIAddress”);
(FARPROC%26amp;) lpfnMAPIFindNext = GetProcAddress(hInstMail,
“MAPIFindNext”);
(FARPROC%26amp;) lpfnMAPIReadMail = GetProcAddress(hInstMail,
“MAPIReadMail”);


3-1-3 登录到电子邮件对象

用户必须在电子邮件系统中登录,才能实现MAPI的各种功能。MAPI提供了登录的三种选择:

登录到一个已经存在的对象。

登录到一个新对象,用编程的方法确定解释新信息。

使用对话框提示用户登录。
我们通常选择登录到一个已经存在的电子邮件对象,因为网络合作用户通常会保持自己的电子邮件程序处于激活状态。登录通常使用MAPI提供的函数lpfnMAPILogon。

lpfnMAPILogon的语法为:
lpfnMAPILogon (lpszProfileName, lpszPassword, flFlags,
ulReserved, lplhSession );

其中,lpszProfileName指向一个256字符以内的登录名称,lpszPassword指向密码,它们均为LPTSTR结构。flFlags为FLAGS结构,其值详见表1。ulReserved必须为0。lplhSession为输出SMAPI的句柄。

表1:lpfnMAPILogon函数中flFlags的值
值 意义
MAPI_FORCE_DOWNLOAD
在函数调用返回之前下载用户的所有邮件。
如果MAPI_FORCE_DOWNLOAD没有被设置,
那么信件能够在函数调用返回后在后台被下载。
MAPI_NEW_SESSION 建立一个新会话,
而不是获得环境的共享会话。如果MAPI_NEW_SESSION没有被设置,
MAPILogon使用现有的共享会话。
MAPI_LOGON_UI 显示一个登录对话框来提示用户输入登录信息。
例如Outlook检查用户电子邮件时便是如此。
MAPI_PASSWORD_UI MAPILogon只允许用户输入电子邮件的密码,
而不许改动账号。

程序示例:
LHANDLE lhSession;
ULONG lResult = lpfnMAPILogon(0, NULL, NULL, 0, 0,
%26amp;lhSession);
if (lResult != SUCCESS_SUCCESS)
//SUCCESS_SUCCESS在MAPI.H中被定义
{
// 错误处理
}


3-2 阅读电子邮件

MAPIFindNext和MAPIReadMail使用与阅读E-mail的两个基本函数。MAPIFindNext用于定位第一封或下一封电子邮件并返回标识号,MAPIReadMail返回以该标识号为基础的电子邮件的内容。另外,一个常用的函数是MAPIFreeBuffer,用于释放内存。

3-2-1 定位到第一封信

要找到第一封信,需要使用MAPIFindNext函数,其函数声明如下:

ULONG FAR PASCAL MAPIFindNext(LHANDLE lhSession,
ULONG ulUIParam, LPTSTR lpszMessageType,
LPTSTR lpszSeedMessageID, FLAGS flFlags,
ULONG ulReserved, LPTSTR lpszMessageID )

其中,lhSession为提交SMAPI的会话句柄 ;ulUIParam为父窗体的句柄;lpszMessageType指向一个字符串,用来鉴别邮件类型,并加以查找;lpszSeedMessageID为指向起始信息ID的指针,其值为0时,MAPIFindNext获得第一封电子邮件;flFlags的值见表2;ulReserved必须为0;lpszMessageID为输出值,它是指向信息ID地址的指针。

表2:MAPIFindNext函数中flFlags的值

值 意义
MAPI_GUARANTEE_FIFO 按邮件发送的时间顺序接受电子邮件。
MAPI_LONG_MSGID 返回信件标识符可达512字符。
MAPI_UNREAD_ONLY 只列举没有阅读过的电子邮件。

程序示例:
// 找到第一条没有阅读的电子邮件
char pMessageID [513];
ULONG lResult = lpfnMAPIFindNext(lhSession, NULL, NULL,
NULL, MAPI_LONG_MSGID | MAPI_UNREAD_ONLY,
0, pMessageID);
3-2-2 阅读信息
当信件ID被获取后,就可以调用MAPIReadMail
阅读实际的E-mail信息了。MAPIReadMail的函数声明如下:
ULONG FAR PASCAL MAPIReadMail(LHANDLE lhSession,
ULONG ulUIParam, LPTSTR lpszMessageID,
FLAGS flFlags, ULONG ulReserved,
lpMapiMessage FAR * lppMessage);
其中,lppMessage为指向MapiMessage的指针;
除flFlags外的其他参数与lpfnFindNext函数的同名参数意义相同,
flFlags参数的值见表3:

表3:MAPIReadMail函数中flFlags的值:
值 意义
MAPI_BODY_AS_FILE 将邮件信息写到一个临时文件中,
并且将它作为第一个附件添加到附件列表中。
MAPI_ENVELOPE_ONLY 只读取邮件标题。
MAPI_PEEK 读完邮件之后不把它标记为“已读”。
MAPI_SUPPRESS_ATTACH MAPIReadMail函数不拷贝附件,
但是将邮件文本写入MapiMessage结构中。

程序示例:
// 读取电子邮件
long nFlags = MAPI_SUPPRESS_ATTACH;
if (!bMarkAsRead)
nFlags = nFlags | MAPI_PEEK;
lResult = lpfnMAPIReadMail(lhSession, NULL, pMessageID,
nFlags, 0, %26amp;pMessage);
if (lResult != SUCCESS_SUCCESS);
return false;

如果调用成功,就可以访问MapiMessage结构了(使用pMessage):
pMessage- >ulReserved:0
pMessage- >lpszSubject:邮件标题
pMessage- >lpszNoteText:邮件信息
pMessage- >lpszMessageType:邮件类型

pMessage- >DateReceived:接收时间
pMessage- >lpszConversationID:邮件所属的会话线程ID
pMessage- >flFlags:其值见表4

表4:MapiMessage结构中的flFlags
值 意义
MAPI_RECEIPT_REQUESTED 接收通知被申请。
客户端应用程序在发送消息时设置该项。
MAPI_SENT 邮件已被发送。
MAPI_UNREAD 邮件是“未读”状态。

pMessage- >lpOriginator:指向MapiRecipDesc结构,包含发件人信息。
pMessage- >nRecipCount:信件者数目。
pMessage- >lpRecips:指向MapiRecipDesc结构数组,包含接收者信息。
pMessage- >nFileCount:附件数量。
pMessage- >lpFiles:指向MapiFileDesc结构数组,
每一个结构包含一个文件附件。


3-2-3 释放内存

在访问另一条信件以前应当释放内存,否则会出现内存泄漏。

程序示例:

// 释放内存
lpfnMAPIFreeBuffer(pMessage);
3-2-4 定位到下一条信件
定位到下一条信件依然使用MAPIFindNext函数,
该函数声明及参数意义详见3-2-1节。下面示范如何定位到下一条信件。

程序示例:
// 定位到下一条没有阅读的信件
ULONG lResult = lpfnMAPIFindNext(lhSession, NULL, NULL,
pMessageID, MAPI_LONG_MSGID|MAPI_UNREAD_ONLY,
0, pMessageID);


3-3 发送电子邮件

发送电子邮件的一般步骤:

1. 建立MapiMessage结构对象

2. 调用MAPIResolveName使发送者名称合法

3. 添加附件

4. 调用MAPISendMail发送电子邮件

5. 调用MAPIFreeBuffer释放内存

下面详细分别详细阐述。

3-3-1 建立MapiMessage结构对象

对于MapiMessage结构,3-2-2节已经做过介绍,下面一步步介绍如何设置其中的值:

1. 为MapiMessage对象分配内存:

MapiMessage message;
Memset(%26amp;message, 0, sizeof(message));

2. 将ulReserved设置为0:

message.ulReserved = 0;

3. 设置信息类型指针lpszMessageType,可以为NULL:

message.lpszMessageType = NULL;

4. 设置信件标题(lpszSubject):

char subject[512];
strcpy(subject, sSubject);
message.lpszSubject = subject;

5. 设置信件内容:

char text[5000];
strcpy(text, sMessage);
message.lpszNoteText = text;

6. 设置flFlags标识,详见3-2-2节中表4:

message.flFlags = MAPI_SENT;

7. 用一个指向MapiRecipDesc结构的指针设置发送者信息(lpOriginator),或将其设置为NULL:

message.lpOriginator = NULL;

8. 设置接收者数目(nRecipCount),可以是1或更多:

message.nRecipCount = 1;

9. 设置接收者信息(lpRecips),详见3-3-2节

10. 设置附件数量(nFileCount)

11. 设置附件信息,详见3-3-3节

b3-3-2 正确设置接收者信息

设置接收者信息时,应当使用MAPIResolveName函数来为MapiRecipDesc结构对象分配内存,并返回一个指针,该指针将被保存在MapiMessage结构的lpRecips中。MAPIResolveName的函数声明如下:

ULONG FAR PASCAL MAPIResolveName(LHANDLE lhSession,
ULONG ulUIParam, LPTSTR lpszName,
FLAGS flFlags, ULONG ulReserved,
lpMapiRecipDesc FAR * lppRecip )

其中lppRecip即为前面提到的返回的指针。除flFlags外其余参数与前几个函数意义相同。flFlags的值详见表5。

表5:MAPIResolveName中flFlags的值
值 意义
MAPI_AB_NOMODIFY 对话框为只读。如果MAPI_DIALOG被设置,
那么该项将被忽略。
MAPI_DIALOG 显示一个名称解决方案的对话框
MAPI_LOGON_UI 如果需要的话,将会显示仪个对话框让用户登录
MAPI_NEW_SESSION 新建一个会话

程序示例:
char recipient[512];
strcpy(recipient, sTo);
lResult = lpfnMAPIResolveName(lhSession, 0, recipient,
0, 0, %26amp;message.lpRecips);


3-3-3 添加附件

下面的程序示例将演示如何在电子邮件中包含附件。只有一点需要说明:MapiFileDesc结构中flFlags的值,详见表6。

表6:MapiFileDesc结构中flFlags的值
值 意义
MAPI_OLE 附件是OLE对象。
MAPI_OLE_STATIC 附件是静态OLE对象。
0 附件将被视为数据文件

程序示例:
// 设置附件信息
CString sPath, sFileName;
MapiFileDesc FileInfo;
char path[512];
char filename[512];
if (sAttachment == “”)
message.nFileCount = 0;
else
{
int nPos = sAttachment.ReverseFind(‘\’);
if (nPos == -1)
{
sPath = sAttachment;
}
else
{
sPath = sAttachment;
sFilename = sAttachment.Mid(nPos +1);
}
strcpy(path, sPath);
strcpy(filename, sFilename);

message.nFileCount = 1;
FileInfo.ulReserved = 0;

FileInfo.flFlags = 0;

FileInfo.nPosition = sMessage.GetLength() –1;
FileInfo.lpszPathName = path;
FileInfo.lpszFileName = filename;
FileInfo.lpFileType = NULL;
message.lpFiles = %26amp; m_FileInfo;
}


3-3-4 发送电子邮件

使用MAPISendMail发送电子邮件,其声明如下:

ULONG FAR PASCAL MAPISendMail (LHANDLE lhSession,
ULONG ulUIParam, lpMapiMessage lpMessage,
FLAGS flFlags, ULONG ulReserved )

其中,flFlags的允许值为MAPI_DIALOG、MAPI_LOGON_UI和MAPI_NEW_SESSION,其意义与前几个函数中同名标识意义相同。

程序示例:

lResult = lpfnMAPISendMail(0, 0, %26amp;m_message, 0, 0);


3-3-5 释放内存

程序示例:
lpfnMAPIFreeBuffer(m_message.lpRecips);

四、小结
本文比较具体的介绍并演示了编写一个电子邮件程序的核心部分,如果读者要编写电子邮件程序,还需要进行的处理:

1. 加上错误处理代码。受篇幅限制,本文的程序示例中只有两处为错误处理留空,比较它们的异同。电子邮件程序是非常容易出错的,因此除这两处外要在主要函数调用完成后都加上错误处理,或使用try throw catch块处理例外。

2. 加上UI处理。

另外,本文所阐述的方法比较简单易行,事实上,有关电子邮件的程序远比这复杂得多,因此读者若需要编写一个功能强大的电子邮件程序,需要精通MAPI和SMTP/POP3等协议;如果读者要编写一个电子邮件服务器,那么不妨在精通MAPI和SMTP/POP3之后,阅读一些有关Exchange Server的资料。

,

文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·使用C#在进度条中显示复制文件的进度-.NET教程,C#语言
·JAVASCRIPT调用JAVA-JSP教程,Java技巧及代码
·Java开源项目Hibernate包作用详解-JSP教程,Java技巧及代码
·新型单相逆变电源的研制
·解读Windows 2000/XP分层驱动模型-.NET教程,Windows开发
·NET中打印包含有格式的 RichTextBox 的内容-.NET教程,Asp.Net开发
·java用于链接数据库的例子(*.properties)-JSP教程,资料/其它
·cable modem及其系统的配置和使用
·asp.net 1.1/ 2.0 中快速实现单点登陆-.NET教程,Asp.Net开发
·持续集成 Java手册-JSP教程,Java技巧及代码
最新文章
·像我一样的菜鸟站长常犯的几种错误_站长心得
·网友开博客真的能赚钱吗?_网赚技巧
·google广告代码可以放到几个网站吗?_网赚技巧
·论坛如何最佳化?adsense最佳化案例_网赚技巧
·姚劲波:站长要用开放平和的心态去坚持_站长访谈
·章征军和他的站长网_站长访谈
·建自己想建的站坚持下去 就是最好的seo_站长心得
·autocad 2008的service pack 1测试版发布_autocad教程
·网站的定位在于选题(后半部分参考市场报)_站长心得
·互联网赚钱的几种基本模式_站长心得
相关主题
  • 用visual c#实现xx邮件接收程序_邮件服务器
  • 用visualbasic5.0设计e-mail程序(mapi)_visualbasic教程
  • 用visualbasic也可以实现p2p_visualbasic教程
  • 用visualbasic自编小游戏_visualbasic教程
  • 用visualbasic与ms-draw开发通用作图软件_visualbasic教程
  • 西部数码虚拟主机

    友情链接
    CNNIC 西部数码
    万网 自助建站
    虚拟主机 asp空间
    域名注册 域名
    域名申请 主页空间
    论坛空间 网站空间
    国际域名 虚拟空间
    空间租用 DDOS防火墙
    成都主机托管 四川主机托管
    主机租用 服务器租用
    网站目录 自助建站
    虚拟主机 网址大全
    软件下载
    自助链接
    虚拟主机资讯 特价虚拟主机
    版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
    关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
    特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
    发表评论 打印  刷新     关闭