使用 MAPI 实现邮件发送
2008-03-19 17:50
253 查看
一、简述
实际上,本文的设计,所使用的只是 simple mapi,可以把它看作是mapi(messaging application programming interface)的一个子集。不过大多数时候,simple mapi提供的功能已经足够使用。本文阐述了一个简单的,用于发送一个带附件的邮件的功能实现。如果需要更复杂的功能,我认为还是老老实实封装smtp和pop3比较好
二、simple mapi 介绍
simple mapi 包括一组很容易使用的函数以及相关的数据结构,可以在c/c++、vb等多种语言中使用。本文是基于vc设计的。
实现一个完整的邮件发送过程,只需要一个函数“mapisendmail()”,完整函数表及相关介绍参查阅msdn library->platform sdk->messaging and collaboration services。
mapi 与邮件系统关系密切,要能够使用mapi的功能,系统必须安装有支持 mapi 的邮件系统,比如outlook、outlook express、eudora、netscape等. 在这里不得不提一下,使用非常广泛的 foxmail (5.0版本)似乎并不支持 mapi,不过并没有深入研究,如果有哪位高手发现实际上是支持的,麻烦告知我如何做。
windows提供了一个文件 mapi.h,包含所有的相关数据类型的定义。
三、功能的设计
我需要实现如下功能:可定制一封邮件,包括至少一个收件人,可选项目有标题、正文、若干抄送人、密件抄送人、附件。能够根据需要选择自动发送(无用户干预),或弹出邮件编写窗口。
为了便于使用和扩展,我用了一个class来实现。
1、mapi库的初始化
包括两个步骤:装载mapi库、得到函数入口地址。
//-------------------------------------------------------------------------------------
m_hlibrary = ::loadlibrary(_t("mapi32.dll"));
if(null == m_hlibrary)
{
return ::getlasterror();
}
// lpmapisendmail 等均定义在 <mapi.h>
m_lpfnmapisendmail = (lpmapisendmail)::getprocaddress(m_hlibrary, _t("mapisendmail"));
// 可以根据需要添加其他函数入口。我的做法是用了一个 initmapi() 函数,一次性将所有函数入口得出,作为类的成员变量保存。随时可以使用
//-------------------------------------------------------------------------------------
2、发送邮件 mapisendmail()
发送邮件功能就是对mapisendmail()的封装。下面解释这个api函数的参数定义。
ulong far pascal mapisendmail(lhandle lhsession, ulong uluiparam, lpmapimessage lpmessage, flags flflags, ulong ulreserved);
lhsession、uluiparam和ulreserved这三个参数,简单地设置为0就可以了。
flflags有三个有效位,分别是 mapi_dialog,mapi_logon_ui,mapi_new_session。
重点是 lpmessage 这个参数,它指向一个mapimessage类型的结构,详细地定义了一个邮件的全部信息。
3、结构 mapimessage
使用时首先定义一个mapimessage类型的变量,将其清零。现在我们只要简单地设定lpszsubject(标题)、lpsznotetext(正文)、lporiginator(发件人)、nrecipcount(收件人计数,包含to、cc、gcc),lprecips(一个包含全部收件人的数组),nfilecount(附件计数)、lpfiles(包含每个附件信息的数组)。
nrecipcount 和 nfilecount 的值一定要与实际的收件人和附件数目相符。
4、结构 mapirecipdesc
必须设置 ulrecipclass、lpszname、lpszaddress
5、结构 mapifiledesc
必须设置的有lpszpathname、nposiotion两个参数
这里有个地方需要特别注意。我在实际编码过程中,有几次 outlook 不能正确弹出窗口(自动发送也不行),但是同样的过程,将邮件客户设为 outlookexpress 就没有问题。但是十分头痛。经过发付查找,发现 nposiotion 这个参数十分重要。它指示附件在邮件中的位置。
对于一些邮件客户端,比如outlookexpress,也许忽略了这个参数,由客户端自动安排。所以没有问题。对于另一些客户端,比如outlook,总是按照这个值的指示来安排的。如果附件数多于一个,这个值如果相同,那么就会造成错误。但是自行计算挺麻烦而且没什么意义。解决的方法是,将其设为 -1,指示客户软件自行安排。:)
四、如何工作?
mapisendmail() 会调用系统默认的邮件客户程序来发送邮件。对于弹出编辑窗的方式,它的行为和另一个函数mapisendmail()差不多,只是可以定制标题、收件人等等,而mapisenddocuments()只是简单地准备一个空白的邮件(包含附件),有关mapisenddocuments()的介绍参见msdn。
对于自动发送。需要在outlook express的安全设置中,取消“当有其他应用程序试图发送邮件时警告”这个选项。对于outlook,还没有找到方法。
我设计的类包括三个接口函数,send(), addfiles(), addrecips(),其中只有send()是必须的。使用时声明一个对象,然后就直接调用send()函数发送邮件。两个add函数只要根据需要在send()之前调用即可。
五、遗留问题
我的开发环境是 windows xp sp2 chs,有如下几个问题,希望有高手可以解决。
1、自动发送时的警告问题。
2、默认outlook express为系统邮件客户端,可以立即发送,如果是outlook,是先放到outlook的发送队列了,这时如果outlook未运行,就一直不会发送。怎样可以保证无论邮件客户软件是否在运行,我的程序都可以立即将邮件发送出去呢?
3、对于默认是“hotmail”的情况,只有以 @hotmail.com 结尾的帐号可以正常发送,而 @msn.com 的则不行。同时,在发送时,hotmail会将硬盘上的附件改名(末尾添加“^”符号)并将文件属性改为只读
实际上,本文的设计,所使用的只是 simple mapi,可以把它看作是mapi(messaging application programming interface)的一个子集。不过大多数时候,simple mapi提供的功能已经足够使用。本文阐述了一个简单的,用于发送一个带附件的邮件的功能实现。如果需要更复杂的功能,我认为还是老老实实封装smtp和pop3比较好
二、simple mapi 介绍
simple mapi 包括一组很容易使用的函数以及相关的数据结构,可以在c/c++、vb等多种语言中使用。本文是基于vc设计的。
实现一个完整的邮件发送过程,只需要一个函数“mapisendmail()”,完整函数表及相关介绍参查阅msdn library->platform sdk->messaging and collaboration services。
mapi 与邮件系统关系密切,要能够使用mapi的功能,系统必须安装有支持 mapi 的邮件系统,比如outlook、outlook express、eudora、netscape等. 在这里不得不提一下,使用非常广泛的 foxmail (5.0版本)似乎并不支持 mapi,不过并没有深入研究,如果有哪位高手发现实际上是支持的,麻烦告知我如何做。
windows提供了一个文件 mapi.h,包含所有的相关数据类型的定义。
三、功能的设计
我需要实现如下功能:可定制一封邮件,包括至少一个收件人,可选项目有标题、正文、若干抄送人、密件抄送人、附件。能够根据需要选择自动发送(无用户干预),或弹出邮件编写窗口。
为了便于使用和扩展,我用了一个class来实现。
1、mapi库的初始化
包括两个步骤:装载mapi库、得到函数入口地址。
//-------------------------------------------------------------------------------------
m_hlibrary = ::loadlibrary(_t("mapi32.dll"));
if(null == m_hlibrary)
{
return ::getlasterror();
}
// lpmapisendmail 等均定义在 <mapi.h>
m_lpfnmapisendmail = (lpmapisendmail)::getprocaddress(m_hlibrary, _t("mapisendmail"));
// 可以根据需要添加其他函数入口。我的做法是用了一个 initmapi() 函数,一次性将所有函数入口得出,作为类的成员变量保存。随时可以使用
//-------------------------------------------------------------------------------------
2、发送邮件 mapisendmail()
发送邮件功能就是对mapisendmail()的封装。下面解释这个api函数的参数定义。
ulong far pascal mapisendmail(lhandle lhsession, ulong uluiparam, lpmapimessage lpmessage, flags flflags, ulong ulreserved);
lhsession、uluiparam和ulreserved这三个参数,简单地设置为0就可以了。
flflags有三个有效位,分别是 mapi_dialog,mapi_logon_ui,mapi_new_session。
重点是 lpmessage 这个参数,它指向一个mapimessage类型的结构,详细地定义了一个邮件的全部信息。
3、结构 mapimessage
使用时首先定义一个mapimessage类型的变量,将其清零。现在我们只要简单地设定lpszsubject(标题)、lpsznotetext(正文)、lporiginator(发件人)、nrecipcount(收件人计数,包含to、cc、gcc),lprecips(一个包含全部收件人的数组),nfilecount(附件计数)、lpfiles(包含每个附件信息的数组)。
nrecipcount 和 nfilecount 的值一定要与实际的收件人和附件数目相符。
4、结构 mapirecipdesc
必须设置 ulrecipclass、lpszname、lpszaddress
5、结构 mapifiledesc
必须设置的有lpszpathname、nposiotion两个参数
这里有个地方需要特别注意。我在实际编码过程中,有几次 outlook 不能正确弹出窗口(自动发送也不行),但是同样的过程,将邮件客户设为 outlookexpress 就没有问题。但是十分头痛。经过发付查找,发现 nposiotion 这个参数十分重要。它指示附件在邮件中的位置。
对于一些邮件客户端,比如outlookexpress,也许忽略了这个参数,由客户端自动安排。所以没有问题。对于另一些客户端,比如outlook,总是按照这个值的指示来安排的。如果附件数多于一个,这个值如果相同,那么就会造成错误。但是自行计算挺麻烦而且没什么意义。解决的方法是,将其设为 -1,指示客户软件自行安排。:)
四、如何工作?
mapisendmail() 会调用系统默认的邮件客户程序来发送邮件。对于弹出编辑窗的方式,它的行为和另一个函数mapisendmail()差不多,只是可以定制标题、收件人等等,而mapisenddocuments()只是简单地准备一个空白的邮件(包含附件),有关mapisenddocuments()的介绍参见msdn。
对于自动发送。需要在outlook express的安全设置中,取消“当有其他应用程序试图发送邮件时警告”这个选项。对于outlook,还没有找到方法。
我设计的类包括三个接口函数,send(), addfiles(), addrecips(),其中只有send()是必须的。使用时声明一个对象,然后就直接调用send()函数发送邮件。两个add函数只要根据需要在send()之前调用即可。
五、遗留问题
我的开发环境是 windows xp sp2 chs,有如下几个问题,希望有高手可以解决。
1、自动发送时的警告问题。
2、默认outlook express为系统邮件客户端,可以立即发送,如果是outlook,是先放到outlook的发送队列了,这时如果outlook未运行,就一直不会发送。怎样可以保证无论邮件客户软件是否在运行,我的程序都可以立即将邮件发送出去呢?
3、对于默认是“hotmail”的情况,只有以 @hotmail.com 结尾的帐号可以正常发送,而 @msn.com 的则不行。同时,在发送时,hotmail会将硬盘上的附件改名(末尾添加“^”符号)并将文件属性改为只读
相关文章推荐
- 使用 MAPI 实现邮件发送
- 使用 MAPI 实现邮件发送
- 使用 MAPI 实现邮件发送
- 怎么使用PHPMailer实现邮件的发送??
- C++ 使用smtp协议发送邮件的简单实现
- 使用java在本地服务器实现简单的邮件的发送与接受
- 记录:使用PHPMailer在ThinkPHP3.2.3上实现发送邮件功能
- 使用yii框架实现邮件发送
- 使用java底层实现邮件的发送(含测试,源码)
- 使用spring实现邮件的发送实例(含测试,源码,注释)
- python使用smtplib模块通过gmail实现邮件发送的方法
- PHP 实现 注册等的邮箱验证 (二)—— 使用 PHPMailer 发送邮件
- java使用Socket实现SMTP协议发送邮件
- JavaWeb中使用JavaMail实现发送邮件功能实例详解
- 使用phantomjs实现highcharts等报表通过邮件发送(本文仅提供完整解决方案和实现思路,完全照搬不去整理代码无法马上得到效果)
- 使用libcurl库实现SMTP发送邮件
- 使用javamail实现发送邮件
- PHP_thinkphp框架使用PHPMailer实现发送邮件的功能,以及各种问题解析
- 使用golang实现批量发送面试邀请邮件
- 使用javascript实现邮件发送按钮60秒倒计