用simple mapi 发送一个带附件的邮件

来源:互联网 发布:中石化造价软件 编辑:程序博客网 时间:2024/06/07 10:56

使用 MAPI 实现邮件发送

原  作:deltacat,修改中
最后更新:2004.09.16
版权声明:随意转载,敬请保持文档及说明完整性

关键字: VC 邮件发送 MAPI


一、简述

  实际上,本文的设计,所使用的只是 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会将硬盘上的附件改名(末尾添加“^”符号)并将文件属性改为只读。

六、结束语

  本文是在给应用程序中添加邮件发送功能的心得。过程中遇到了很多问题,将他写出来,主要是给自己一个记录,也是我第一次将自己的编程过程整理成文档。
  若本文还能帮到有同样需要的朋友,会令我很开心。也希望有这方面经验的朋友可以解决我的遗留问题。


后篇 

 在VC中调用默认的电子邮件程序发送邮件


很多时候大家需要在程序中发送邮件,自己编又太麻烦,怎么办,呵呵,有现成的! 



1、想省事儿的,用ShellExecute函数: 



ShellExecute(NULL,NULL,"mailto:email@263.net",NULL,NULL,SW_SHOW); 




2、如果想自己多处理一些东西的话,比如加上默认的帐号、密码、附件等,就可以调用系统的Mapi函数。具体的用法大家可以去查MSDN都是以MAPI开头的,如MAPILogon、MAPISendMail等。下面这段代码演示如何调用默认的邮件程序发送邮件。 



#include "mapi.h" 

void CTestMapiDlg::OnSendMail() 

HMODULE hMod = LoadLibrary("MAPI32.DLL"); 

if (hMod == NULL) 

AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD); 
return; 


ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG); 
(FARPROC&)lpfnSendMail = GetProcAddress(hMod, "MAPISendMail"); 

if (lpfnSendMail == NULL) 

AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL); 
return; 


ASSERT(lpfnSendMail != NULL); 

TCHAR szPath[_MAX_PATH] = "C:\Winnt\setup.log"; 
TCHAR szTitle[_MAX_PATH] = "setup.log"; 

// prepare the file description (for the attachment) 
MapiFileDesc fileDesc; 
memset(&fileDesc, 0, sizeof(fileDesc)); 
fileDesc.nPosition = (ULONG)-1; 

fileDesc.lpszPathName = szPath; 
fileDesc.lpszFileName = szTitle; 

// prepare the message (empty with 1 attachment) 
MapiMessage message; 
memset(&message, 0, sizeof(message)); 
message.nFileCount = 1; 
message.lpFiles = &fileDesc; 

int nError = lpfnSendMail(0, 0, 
&message, MAPI_LOGON_UI&brvbar;MAPI_DIALOG, 0); 

// after returning from the MAPISendMail call, the window must 
// be re-enabled and focus returned to the frame to undo the workaround 
// done before the MAPI call. 
if (nError != SUCCESS_SUCCESS && 
nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE) 

AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND); 


【转】MAPI32::MAPISendMail以邮件附件形式发送文件

MAPISendMail

The MAPISendMail function sends a message, this function differs from the MAPISendDocuments function in that it allows greater flexibility in message generation.

Header file:MAPI.H

ULONG FAR PASCAL MAPISendMail(

LHANDLE lhSession,

 ULONG ulUIParam,

lpMapiMessage lpMessage,

 FLAGS flFlags,

ULONG ulReserved )

Parameters

lhSession

[in] handle to a simple MAPI session or zero. If the value of  the lhSession parameter is zero, MAPI logs on the user and creates a session that exists only for the duration of the call. This temporary session can be an existing shared session or a new one. If necessary, the logon dialog box is displayed.

ulUIParam

[in] Parent window handle or zero.indicating that if a dialog box is displayed, it is application modal. If the ulUIParam contains a parent window handle, it is of type HWND (cast TO A ULONG). If no dialog box is displayed during the call, ulUIParam is ignored.

lpMessage

[in] pointer to a MapiMessage structure containing the message to be sent. If the MAPI_DIALOG flag is not set, the nRecipCount and lpRecips members must be valid for sucessful message delivery. Client application can set the flFlags member to MAPI_RECEIPT_REQUESTED to request a read report. All other members are ignored and unused pointers should be NULL.

flFlags

[in] bitmark of option flags. The following flags can be set:

MAPI_DIALOG

A dialog box should be displayed to prompt the user for recipients and other sending options. When MAPI_DIALOG is not set, at least one recipient must be specified.

MAPI_LOGON_UI

A dialog box should be displayed to prompt the user to log on if required. When the MAPI_LOGON_UI is not set, the client application does not display a logon dialog box and returns an error value if the user is not logged on. MAPISendMail ignores this flag if the lpszMessageID parameter is empty.

MAPI_NEW_SEEEION

An attempt should be made to create a new session rather that acquire the environment's shared session. If the MAPI_SESSION flag is not set, MAPISendMail uses an existing share session.

ulReserved

Reserved; must be zero.

Return Values

MAPI_E_AMBIGUOUS_RECIPIENT
A recipient matched more than one of the recipient descriptor structures and MAPI_DIALOG was not set. No message was sent.
MAPI_E_ATTACHMENT_NOT_FOUND
The specified attachment was not found. No message was sent.
MAPI_E_ATTACHMENT_OPEN_FAILURE
The specified attachment could not be opened. No message was sent.
MAPI_E_BAD_RECIPTYPE
The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC. No message was sent.
MAPI_E_FAILURE
One or more unspecified errors occurred. No message was sent.
MAPI_E_INSUFFICIENT_MEMORY
There was insufficient memory to proceed. No message was sent.
MAPI_E_INVALID_RECIPS
One or more recipients were invalid or did not resolve to any address.
MAPI_E_LOGIN_FAILURE
There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed. No message was sent.
MAPI_E_TEXT_TOO_LARGE
The text in the message was too large. No message was sent.
MAPI_E_TOO_MANY_FILES
There were too many file attachments. No message was sent.
MAPI_E_TOO_MANY_RECIPIENTS
There were too many recipients. No message was sent.
MAPI_E_UNKNOWN_RECIPIENT
A recipient did not appear in the address list. No message was sent.
MAPI_E_USER_ABORT
The user canceled one of the dialog boxes. No message was sent.
SUCCESS_SUCCESS
The call succeeded and the message was sent.

Remarks

The MAPISendMail function sends a standard message, with or without any user interface. The profile must be configured so that MAPISendMail can open the default service paroviders without requiring user interface. However, if the flFlags parameter is set to MAPI_NEW_SESSION, disallowing the use of a shared session, and the profile requires a passsword, MAPI_LONON_UI must be set or  the function will fall. Client application can avoid this situation by using an explicit profile without a password or by using the default profile without a password.

Client application can provide a full or partial of recipient names, subject text,file attachments,or message text. If any information is missing, MAPISendMail can prompt the user for it. If no information is missing, either the message can be sent as if or the user can be prompted to verify the information, changing values if necessary.

A successful return form MAPISendMail does not necessarily imply recipient validation. The message might not have been sent to all recipients. Depending on the transport provider, recipient validation can be a lengthy process.

A NULL value for the lpszSubject member of the MapiMessage structure pointed to by the lpMessage parameter indicates that there is not text for the subject of the message.

A NULL value for the lpszNoteText member indicate that there is no message text. Some client application can truncate subject lines that are too long or contain carriage returns, line feeds, or form feeds.

Each paragraph should be terminated with a CR(OXOD), and LF(0X0a), or a CRLF(0X0D0A). MAPISendMail wraps lines as appropriate. If the text exceeds system limits, the function returns the MAPI_E_TEXT_TOO_LARGE values.

The lpszMessageType member of the MapiMessage structure pointed by lpMessage is used only by non_IPM applications. Applications that handle IPM message can set it to NULL or have it point to an empty string.

The number of attachments per message of the MapiMessage structure can be limited in some messaging systems. If the limit is exceeded, the MAPI_E_TOO_MANY_FILES value if returned. If no files are specified, a pointer value of NULL should be assigned to the files do not affect the contents of the message. The files must be closed when they are copied. Do not attempt to display attachments outside the range of the message text.

Some messaging systems can limit the number of recipients per message. A pointer value of NUL  for the lpRecipts member in the MapiMessage structure pointed by the lpMessage indicates no recipients. If the client application passes a non-NUll value indicating a number of recipients exceeding the system limit, MAPISendMail returns the MAPI_E_TOO_MANY_RECIPIENTS value. If the value of the nRecipCount member in the MapiMessage structure is 0, the MAPI_DAILOG flag must be present in the call to MAPISendMail.

Note that the lpRecips member in the MapiMessage structure can include either an entry identifier, the recipient's name, and address, or a name and address pair. The following table show how MAPISendMail handles the variety of information that can be specified:

InformationActionentry identifierNo name resolution; the name and address are ignored.nameName resolved using the Simple MAPI resolution rules.addressNo name resolution; address is used for both message delivery and for displaying the recipient name.name and addressNo name resolution; name used only for displaying the recipient name.

Client applications that send messages to custom recipients can avoid name resolution. Such clients should set thelpszAddress member of the MapiRecipDesc structure pointed to by the lpRecips member of the MapiMessage structure pointed to by the lpMessage parameter to the custom address.

MAPISendMail does not require an originator-type recipient to send a message.

MapiMessage (simple MAPI)

A MapiMessage structure contains information about a message.

Header file: MAPI.H

typedef struct {

ULONG ulReserved;

LPTSTR lpszSubject;

LPTSTR lpszNoteText;

LPTSTR lpszMessageType;

LPTSTR lpszDateReceived;

LPTSTR lpszConversationID;

FLAGS flFlags;

lpMapiRecipDesc lpOriginator;

ULONG nRecipCount;

lpMapiRecipDesc lpRecips;

ULONG nFileCount;

lpMapiFileDesc lpFiles;

}MapiMessage, FAR *lpMapiMessage;

Members

ulReserved

Reserved, must be zero.

lpszSubject

pointer to the text string describing the message subject, typically limited to 256 characters or less. If this member is empty or NULL, the user has not entered subject text.

lpszNoteText

pointer to a string containing the message text. If this member is empty or NULL, there is no message text.

lpszMessageType

Pointer to a string indicating a non-IPM type of message. Client application can select message types for their non_IPM messages. Clients that only support IPM messages can ignore the lpszMessageType member when reading messages andset it to empty or NULLwhen sending messages.

lpszDateReceived

Pointer to a string indicating the date when the message was received. The format is YYYY/MM/DD HH:MM, using a 24-hour clock.

lpszConversationID

pointer to a string identifying the conversation thread to which the message belongs. some messaging system can ignore and not return this member.

flFlagsBitmark of message status flags. The following flags can be set:

MAPI_RECEIPT_REQUESTED
A receipt notification is requested. Client applications set this flag when sending a message.
MAPI_SENT
The message has been sent.
MAPI_UNREAD
The message has not been read.

lpOriginatorPointer to a MapiRecipDescstructure containing information about the sender of the message.nRecipCountThe number of message recipient structures in the array pointed to by the lpRecipsmember. A value of zero indicates no recipients are included.lpRecipsPointer to an array of MapiRecipDescstructures, each containing information about a message recipient.nFileCountThe number of structures describing file attachments in the array pointed to by the lpFiles member. A value of zero indicates no file attachments are included.lpFilesPointer to an array ofMapiFileDesc structures, each containing information about a file attachment.

 

MapiFileDesc (simple MAPI)

A MapiFileDesc structure contains information about a file containing a message attachment stored as a temporary file. That file can contain a static OLE object, an embedded OLE object, and embedded message, and other types of files.

typedef struct {

ULONG ulReserved;

ULONG flFlags;

ULONG nPosition;

LPTSTR lpszPathName;

LPTSTR lpszFileName;

LPVOID lpFileType;

} MapiFileDesc, FAR *lpMapiFileDesc;

Members
ulReserved
Reserved; must be zero.
flFlags
Bitmask of attachment flags. The following flags can be set:
MAPI_OLE
The attachment is an OLE object. If MAPI_OLE_STATIC is also set, the attachment is a static OLE object. If MAPI_OLE_STATIC is not set, the attachment is an embedded OLE object.
MAPI_OLE_STATIC
The attachment is a static OLE object.

If neither flag is set, the attachment is treated as a data file.

 

 

nPosition
An integer used to indicate where in the message text to render the attachment. Attachments replace the character found at a certain position in the message text. That is, attachments replace the character in the MapiMessage structure field NoteText[nPosition]. A value of – 1 (0xFFFFFFFF) means the attachment position is not indicated; the client application will have to provide a way for the user to access the attachment.
lpszPathName
Pointer to the fully qualified path of the attached file. This path should include the disk drive letter and directory name.
lpszFileName
Pointer to the attachment filename seen by the recipient, which may differ from the filename in the lpszPathName member if temporary files are being used. If the lpszFileName member is empty or NULL, the filename from lpszPathNameis used.
lpFileType
Pointer to the attachment file type, which can be represented with a MapiFileTagExt structure. A value of NULL indicates an unknown file type or a file type determined by the operating system.

Remarks

Simple MAPI works with three kinds of embedded attachments:

  • Data file attachments
  • Editable OLE object file attachments
  • Static OLE object file attachments

Data file attachments are simply data files. OLE object file attachments are OLE objects that are displayed in the message text. If the OLE attachment is editable, the recipient can double-click it and its source application will be started to handle the edit session. If the OLE attachment is static, the object cannot be edited. The flag set in the flFlags member of the MapiFileDesc structure determines the kind of a particular attachment. Embedded messages can be identified by a .MSG extension in the lpszFileNamemember.

OLE object files are file representations of OLE object streams. The client application can recreate an OLE object from the file by calling the OLE functionOleLoadFromStreamwith an OLESTREAM object that reads the file contents. If an OLE file attachment is included in an outbound message, the OLE object stream should be written directly to the file used as the attachment.

When using the MapiFileDesc member nPosition, the client application should not place two attachments in the same location. Client applications might not display file attachments at positions beyond the end of the message text.

Example

复制代码
/********************************************************************** 函数名称:CSendEMailDlg::OnSendMapi* 说明:  调用MAPI函数发送邮件。摘自 VC98/MFC/SRC/DOCMAPI.CPP* 作者:  Geng* 时间 : 2003-04-22 20:08:30 *********************************************************************//*  m_list 为ListControl的变量 ,程序将ListControl中列出的所有item以附近形式发送,如果你的系统安装了Outlook发送邮件器,那么会启动它来作为邮件发送默认程序*//* code 为非Unicode版本 */void CSendEMailDlg::OnSendMapi() {    UpdateData(true);     //加载MAPI32.DLL动态库    HMODULE hMod = LoadLibrary(_T("MAPI32.DLL"));     if (hMod == NULL)    //加载动态库失败    {        AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD);        return;    }     //获取发送邮件的函数地址    ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG);    (FARPROC&)lpfnSendMail = GetProcAddress(hMod, "MAPISendMail");     if (lpfnSendMail == NULL)    {        AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL);        return;    }     int nFileCount = m_list.GetCount();    //有多少个附件需要发送     //分配内存保存附件信息    不能使用静态数组,因为不知道要发送附件的个数    MapiFileDesc* pFileDesc = (MapiFileDesc*)malloc(sizeof(MapiFileDesc) * nFileCount);    memset(pFileDesc,0,sizeof(MapiFileDesc) * nFileCount);     //分配内存保存附件文件路径    TCHAR* pTchPath = (TCHAR*)malloc(MAX_PATH * nFileCount);     CString szText;    for(int i = 0;i < nFileCount;i++)    {        char* p = pTchPath + MAX_PATH * i;        m_list.GetText(i,szText);       strcpy(p,szText);        (pFileDesc + i)->nPosition = (ULONG)-1;        (pFileDesc + i)->lpszPathName = p;        (pFileDesc + i)->lpszFileName = p;    }     //收件人结构信息    /*MapiRecipDesc recip;    memset(&recip,0,sizeof(MapiRecipDesc));    recip.lpszAddress    = m_szEmailMAPI.GetBuffer(0);    recip.ulRecipClass = MAPI_TO;*/     //邮件结构信息    MapiMessage message;    memset(&message, 0, sizeof(message));    message.nFileCount    = nFileCount;                //文件个数    message.lpFiles        = pFileDesc;                //文件信息    //message.nRecipCount = 0;                        //收件人个数    //message.lpRecips     = NULL;//&recip;                    //收件人    //message.lpszSubject    = NULL; //m_szSubject.GetBuffer(0);    //主题    //message.lpszNoteText= NULL;//m_szText.GetBuffer(0);    //正文内容     //保存本程序窗口指针,因为发完邮件后要返回本程序的窗口    CWnd* pParentWnd = CWnd::GetSafeOwner(NULL, NULL);     //发送邮件    int nError = lpfnSendMail(0, 0,                    &message, MAPI_LOGON_UI|MAPI_DIALOG, 0);     if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT             && nError != MAPI_E_LOGIN_FAILURE)    {        AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND);    }     //返回程序    pParentWnd->SetActiveWindow();     //不要忘了释放分配的内存    free(pFileDesc);    free(pTchPath);    FreeLibrary(hMod);} 
//imapi.h================================/*  * $Header:$  *  * $Log:$  */ //#include   class CIMapi { public:      CIMapi();      ~CIMapi();   enum errorCodes  {   IMAPI_SUCCESS = 0,   IMAPI_LOADFAILED,   IMAPI_INVALIDDLL,   IMAPI_FAILTO,   IMAPI_FAILCC,   IMAPI_FAILATTACH  };  // Attributes  void   Subject(LPCTSTR subject) { m_message.lpszSubject = (LPTSTR) subject; }  void   Text(LPCTSTR text)   { m_text = text; }   UINT   Error();  void   From(LPCTSTR from)   { m_from.lpszName = (LPTSTR) from; }   static BOOL  HasEmail();  // Operations  BOOL   To(LPCTSTR recip);  BOOL   Cc(LPCTSTR recip);  BOOL   Attach(LPCTSTR path, LPCTSTR name = NULL);    BOOL   Send(ULONG flags = 0);  private:  BOOL   AllocNewTo();   MapiMessage  m_message;  MapiRecipDesc m_from;  UINT   m_error;  CString   m_text;   ULONG (PASCAL *m_lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG);    static HINSTANCE m_hInstMail;  static BOOL  m_isMailAvail; }; //imapi.cpp==================================================/*   *  $Header:$   *   *  $Log:$   */   #include "stdafx.h"    #include <MAPI.H>    #include "imapi.h"       HINSTANCE CIMapi::m_hInstMail = (HINSTANCE) NULL;   BOOL      CIMapi::m_isMailAvail = (BOOL) -1;      CIMapi::CIMapi()   {       m_error = 0;                                        //  Initially error free           memset(&m_message, 0, sizeof(MapiMessage));       memset(&m_from, 0, sizeof(MapiRecipDesc));       m_message.lpOriginator = &m_from;       m_from.ulRecipClass = MAPI_ORIG;          if (m_hInstMail == (HINSTANCE) NULL)                //  Load the MAPI dll            m_hInstMail = ::LoadLibraryA("MAPI32.DLL");          if (m_hInstMail == (HINSTANCE) NULL)       {           AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD);           m_error = IMAPI_LOADFAILED;           return;       }          ASSERT(m_hInstMail != (HINSTANCE) NULL);            //  Now get the pointer to the send function        (FARPROC&) m_lpfnSendMail = GetProcAddress(m_hInstMail, "MAPISendMail");          if (NULL == m_lpfnSendMail)       {           AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL);           m_error = IMAPI_INVALIDDLL;           return;       }          ASSERT(m_lpfnSendMail != NULL);   }      CIMapi::~CIMapi()   {       if (m_hInstMail != (HINSTANCE) NULL)           ::FreeLibrary(m_hInstMail);          m_hInstMail = (HINSTANCE) NULL;              free(m_message.lpFiles);       free(m_message.lpRecips);   }      BOOL CIMapi::HasEmail()   {       if (m_isMailAvail == (BOOL) -1)           m_isMailAvail = ::GetProfileInt(_T("MAIL"), _T("MAPI"), 0) != 0 && SearchPath(NULL, _T("MAPI32.DLL"), NULL, 0, NULL, NULL) != 0;          return m_isMailAvail;   }      UINT CIMapi::Error()   {       UINT temp = m_error;          m_error = IMAPI_SUCCESS;       return temp;   }      BOOL CIMapi::AllocNewTo()   {       //  Allocate a new MapiRecipDesc structure and initialise it to all zeros        m_message.lpRecips = (MapiRecipDesc *) realloc(m_message.lpRecips, (m_message.nRecipCount + 1) * sizeof(MapiRecipDesc));       memset(&m_message.lpRecips[m_message.nRecipCount], 0, sizeof(MapiRecipDesc));          ASSERT(m_message.lpRecips);       return m_message.lpRecips != (MapiRecipDesc *) NULL;   }      BOOL CIMapi::To(LPCTSTR recip)   {       if (AllocNewTo())       {           //  We succeeded in allocating a new recipient record            m_message.lpRecips[m_message.nRecipCount].lpszName = (LPTSTR) recip;           m_message.lpRecips[m_message.nRecipCount].ulRecipClass = MAPI_TO;           m_message.nRecipCount++;           return TRUE;       }          m_error = IMAPI_FAILTO;       return FALSE;   }      BOOL CIMapi::Cc(LPCTSTR recip)   {       if (AllocNewTo())       {           //  We succeeded in allocating a new recipient record            m_message.lpRecips[m_message.nRecipCount].lpszName = (LPTSTR) recip;           m_message.lpRecips[m_message.nRecipCount].ulRecipClass = MAPI_CC;           m_message.nRecipCount++;           return TRUE;       }          m_error = IMAPI_FAILCC;       return FALSE;   }      BOOL CIMapi::Attach(LPCTSTR path, LPCTSTR name)   {       //  Add a new attachment record        m_message.lpFiles = (MapiFileDesc *) realloc(m_message.lpFiles, (m_message.nFileCount + 1) * sizeof(MapiFileDesc));       memset(&m_message.lpFiles[m_message.nFileCount], 0, sizeof(MapiFileDesc));          ASSERT(m_message.lpFiles);              if (m_message.lpFiles == (MapiFileDesc *) NULL)       {           m_error = IMAPI_FAILATTACH;           return FALSE;       }          m_message.lpFiles[m_message.nFileCount].lpszPathName = (LPTSTR) path;       m_message.lpFiles[m_message.nFileCount].lpszFileName = (LPTSTR) name;       m_message.nFileCount++;       return TRUE;   }      BOOL CIMapi::Send(ULONG flags)   {       CWaitCursor wait;       int         offset = m_text.GetLength();          //  Add 1 space per attachment at the end of the body text.        m_text += CString(' ', m_message.nFileCount);          //  Set each attachment to replace one of the added spaces at the end of the body text.        for (UINT i = 0; i < m_message.nFileCount; i++)           m_message.lpFiles[i].nPosition = offset++;          m_message.lpszNoteText = (LPTSTR) (LPCTSTR) m_text; //  Set the body text           // prepare for modal dialog box        AfxGetApp()->EnableModeless(FALSE);       HWND hWndTop;       CWnd* pParentWnd = CWnd::GetSafeOwner(NULL, &hWndTop);          // some extra precautions are required to use MAPISendMail as it        // tends to enable the parent window in between dialogs (after        // the login dialog, but before the send note dialog).        pParentWnd->SetCapture();       ::SetFocus(NULL);       pParentWnd->m_nFlags |= WF_STAYDISABLED;          int nError = m_lpfnSendMail(0, (ULONG) pParentWnd->GetSafeHwnd(), &m_message, MAPI_LOGON_UI | flags, 0);          // after returning from the MAPISendMail call, the window must        // be re-enabled and focus returned to the frame to undo the workaround        // done before the MAPI call.        ::ReleaseCapture();       pParentWnd->m_nFlags &= ~WF_STAYDISABLED;          pParentWnd->EnableWindow(TRUE);       ::SetActiveWindow(NULL);       pParentWnd->SetActiveWindow();       pParentWnd->SetFocus();              if (hWndTop != NULL)           ::EnableWindow(hWndTop, TRUE);              AfxGetApp()->EnableModeless(TRUE);          if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE)       {           AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND);           return FALSE;       }          return TRUE;   } //在你的dlg.cpp #include imapi.h//你的dlg.cpp 的按钮事件===================================void 你的DLG::OnBnClickedButton1(){  CIMapi  mail; mail.To("Tofirst@qq.com");  mail.To("Tosecond@qq.com"); mail.Cc("CCfirst@qq.com");    mail.From("aa@qq.com");    mail.Subject("Test Email");     // mail.Attach("somefilename");    //   // mail.Attach("someotherfile", "different_name_for_recipient");  mail.Text("Body text for this email");   mail.Send();}


0 0