Programming °æ (¾«»ªÇø)
×÷ ¼Ò: crystal (»¨) on board 'programming'
Ìâ Ä¿: VC4.0ÖеÄMAPI
À´ Ô´: ¹þ¶û±õ×϶¡ÏãÕ¾
ÈÕ ÆÚ: Sun Aug 10 11:59:19 1997
³ö ´¦: crystal.bbs@bbs.net.tsinghua.edu.cn
·¢ÐÅÈË: midi (ÃÔµÑ), ÐÅÇø: Program
±ê Ìâ: VC4.0ÖеÄMAPI
Writing Messaging Applications with MAPI
+ The MAPI Architecture
+ Types of MAPI Support
+ Service Providers
+ MAPI Profiles
+ MAPI APIs
+ Simple MAPI
+ Common Messaging Calls
+ Extended MAPI
+ OLE Messaging
+ MAPI Support in MFC
+ MAPI Support in CDocument
+ MAPI and AppWizard
+ Summary
35 — Writing Messaging Applications with MAPI
Writing messaging-enabled applications is no longer the task of a few
corporate programmers working on enterprise-wide system integration
projects. Microsoft Exchange and MAPI services are now available on every
Windows 95 desktop; and with the recent phenomenal growth of the Internet,
users in increasing numbers demand messaging features in end-user
applications. Solutions that were developed for corporate networks
yesterday are used on home computers today; if this sounds like an
outrageous claim, consider the fact that I am submitting the very pages of
this manuscript by dragging the files into Microsoft Exchange and letting
them go.
Microsoft recognized this fact when it decided to add the requirement for
some level of MAPI support to its Windows 95 Logo Program. For applications
to qualify under this program, it is now necessary for them to support, at
the very minimum, a Send command that enables them to send a document to a
MAPI recipient. (Obviously, if your application is conceptually different,
such as a game program, MAPI support is not required.)
The MAPI acronym stands for Messaging Applications Programming Interface.
But what exactly is MAPI? How is MAPI implemented? And, most importantly,
in what way can applications utilize MAPI services most efficiently? These
are the questions that I attempt to answer in the present chapter.
Be aware that the purpose of this chapter is not to provide an introduction
to MAPI at the level required to develop MAPI providers. Such discussion
would itself warrant a book. Instead, I am trying to present an overview of
MAPI as an application interface, with special emphasis on MAPI usage from
within MFC framework applications.
---------------------------------------------------------------------------
[Image]NOTE: Throughout this chapter, the MAPI architecture I describe
corresponds to MAPI in Windows 95 or in upcoming versions of Windows NT.
Earlier versions of Microsoft Mail, although they provide limited support
for Simple MAPI and CMC, do not provide full Extended MAPI support, nor are
they compatible with the architecture described in this chapter.
---------------------------------------------------------------------------
The MAPI Architecture
What exactly is MAPI? Is it the Microsoft Exchange Client that is supplied
with Windows 95? Is it the much anticipated Exchange Server? Is it the MAPI
spooler that is quietly running in the background whenever Exchange is
started?
The answer is, none of the above. MAPI is not an application, a DLL, or a
system service; rather, it is a series of specifications. Although
Microsoft is the prime supplier of MAPI components, it is by no means
necessary to have a single Microsoft component in order to use MAPI (nor is
it necessary to use a Windows or Win32 platform, actually). You can have a
MAPI-compliant system with third party message store, address book, and
transport providers on a non-Windows operating system. MAPI is part of what
Microsoft calls WOSA, the Windows Open Services Architecture, that consists
of a common set of APIs for distributed computing.
MAPI, in fact, can be viewed as two independent sets of APIs that link
client applications on the one hand with service providers on the other
(Figure 35.1).
Figure 35.1. The MAPI architecture.
Why several APIs? The reasons are partly historical. First, Microsoft
released the specifications for Simple MAPI, which included about a dozen
fundamental calls that enabled applications to use messaging. The Common
Messaging Calls (CMC)API has been developed as a platform-independent
replacement for Simple MAPI. It also contains about 10 fundamental calls
that provide access to basic messaging services. In contrast, Extended MAPI
is a large, complex, evolving specification that not only provides an
application programming interface for client applications but for service
providers as well. OLE Messaging, an API specifically developed for Visual
Basic and Visual C++ applications, uses the OLE automation architecture.
Before we plunge into exploring the APIs, the next section gives us a
closer look at the MAPI architecture itself.
Types of MAPI Support
There are three distinct levels of MAPI support that applications can
provide.
The simplest MAPI applications are messaging-aware applications. These
applications do not depend on the presence of MAPI to perform their
functions; they merely provide some simple MAPI functionality. The Windows
95 WordPad, which provides a Send command in its File menu, is a good
example for a messaging-aware application. In contrast, messaging-enabled
applications require MAPI to be present in order to offer full
functionality. While these applications may function when MAPI is not
present, they cannot offer the full range of their services under these
conditions. A perfect example for a messaging-enabled application is
Microsoft Schedule+; while this program can be used as a stand-alone
personal information manager, many of its capabilities do not make sense
unless it is running on a system with MAPI installed.
At the top of the hierarchy are messaging-based applications. Running these
applications requires that the full range of MAPI services (message store,
address book, transport) be present and available. These applications are
also often referred to as workgroup applications. A good example for a
workgroup application is the Microsoft Exchange client; I will spare you
the explanation why this application cannot be run on a stand-alone system
with no MAPI support.
The next section presents a brief tour of MAPI service providers; then we
can examine how the various APIs are used in applications that provide
these different levels of support
Service Providers
MAPI service providers are the components that collectively implement MAPI
service on a system. There are three distinct types of service providers:
message stores, address books, and transports.
Address books contain one or more lists of recipients. An address book
provider implements a specific set of interfaces through which messaging
applications or other providers can gain access to address entries or lists
of addresses.
Message stores are hierarchical depositories of MAPI messages. A message
consists of a multitude of properties that include the sender of the
message, the recipient, the date, subject, message body, and many other
items. Message store providers implement some form of persistent storage
for messages (for example, a local disk file) and provide a set of
interfaces through which messaging applications and other providers can
enumerate messages in the message store, retrieve specific message
properties, or retrieve a set of messages.
Transport providers represent the link between the local system and remote
systems. Transport providers take outgoing messages, establish connections
to remote systems, and transmit messages in a format that the remote system
can comprehend. Transport providers also accept incoming messages from the
remote system, translate these into MAPI message objects as necessary, and
place them into the local message store. A good example of a transport
provider is the Microsoft Internet transport provider, which connects to
remote systems using Windows Sockets and uses SMTP (Simple Mail Transfer
Protocol) for outgoing and POP (Post Office Protocol) for incoming
messages. Outgoing messages are translated into a readable ASCII form;
incoming messages are translated from such form into MAPI message objects.
All providers are represented in the form of DLLs. The set of DLLs that are
to be loaded for a MAPI session is determined by MAPI profiles.
MAPI Profiles
The "glue" that holds MAPI components together is the MAPI Spooler. The
MAPI Spooler is a separate process that facilitates message receipt and
delivery. It is typically the MAPI Spooler that passes submitted messages
to transport providers and accepts incoming messages from them. The MAPI
Spooler implements a store-and-forward architecture; that is, messages
submitted are "spooled" by the spooler to the appropriate transport
provider when it becomes available. This capability is vital on systems
with large message volumes and many remote connections.
Actually, it is also the MAPI Spooler that is responsible for loading and
initializing service providers. But how does the spooler know which service
providers to load?
The answer is MAPI profiles. MAPI profiles are registry entries that
specify the current MAPI configuration.
These registry entries can be found under the following registry key:
HKEY_CURRENT_USER\
Software\
Microsoft\
Windows Messaging Subsystem\
Profiles
Note that the MAPI profile registry entries are generally not readable by
human beings and should not be edited manually.
There can be several profiles defined for a user. Each profile describes a
series of service providers and their operating parameters. For example, a
typical profile may include the Microsoft Personal Information Store
(message store provider), the Microsoft Personal Address Book (address book
provider), Microsoft Fax (transport provider), and the Microsoft Network
Online Service (address book and transport). MAPI profiles can be edited
using the Microsoft Exchange client; select the Services command from its
Tools menu (Figure 35.2).
Figure 35.2. Editing a MAPI profile.
MAPI APIs
The different APIs serve different types of MAPI applications.
Messaging-aware and messaging-enabled applications can use both Simple MAPI
and CMC. The main advantage of using CMC is complete platform independence.
It is recommended that newer applications use CMC in place of Simple MAPI.
Messaging-based applications (not to mention service providers) require
access to the full MAPI API set and thus should use Extended MAPI.
OLE Messaging is used by Visual Basic and Visual C++ applications. OLE
Messaging provides a richer API than CMC or Simple MAPI but falls short of
the functionality of the full Extended MAPI set.
Simple MAPI
Simple MAPI provides a series of functions that enable applications to
establish a MAPI session, perform messaging functions, and shut down the
session.
The simplest way to use Simple MAPI is via the MAPISendDocuments function.
This function can be used to create a standard MAPI message with one or
more file attachments. MAPISendDocuments always displays a dialog where the
user can specify recipients, sending options, and the message text. This is
demonstrated by the program in Listing 35.1. This program sends a message
using MAPISendDocuments with the file c:\autoexec.bat embedded in it. You
can compile this program from the command line by typing cl sendmsg.c
user32.lib.
Listing 35.1. Using MAPISendDocuments.
#include <windows.h>
#include <mapi.h>
LPMAPISENDDOCUMENTS lpfnMAPISendDocuments;
void SendMsg(HWND hwnd)
{
(*lpfnMAPISendDocuments)((ULONG)hwnd, ";", "C:\\AUTOEXEC.BAT",
"AUTOEXEC.BAT", 0);
MessageBox(hwnd, "Message sent", "", MB_OK);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_LBUTTONDOWN:
SendMsg(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR d3, int nCmdShow)
{
MSG msg;
HWND hwnd;
WNDCLASS wndClass;
HANDLE hMAPILib;
hMAPILib = LoadLibrary("MAPI32.DLL");
lpfnMAPISendDocuments = (LPMAPISENDDOCUMENTS)GetProcAddress(
hMAPILib, "MAPISendDocuments");
if (hPrevInstance == NULL)
{
memset(&wndClass, 0, sizeof(wndClass));
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.lpszClassName = "HELLO";
if (!RegisterClass(&wndClass)) return FALSE;
}
hwnd = CreateWindow("HELLO", "HELLO",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
DispatchMessage(&msg);
FreeLibrary(hMAPILib);
return msg.wParam;
}
A much more flexible way of sending messages is through MAPISendMail.
Through a series of structures, you can specify the recipient and contents
of the message. MAPISendMail makes it possible to send mail without
presenting a user interface whatsoever. Thus, MAPISendMail can also be
used, for example, from command-line applications.
MAPISendMail is typically used within a MAPI session that is started by a
call to MAPILogon and terminated by calling MAPILogoff. This usage of
MAPISendMail is demonstrated by the program in Listing 35.2, which sends a
simple text message to president@whitehouse.gov without displaying a user
interface. (For the sake of the sanity of Mr. Clinton's staff, do change
the mail address before you start experimenting with this program!)
Listing 35.2. Using Simple MAPI in a console application.
#include <windows.h>
#include <stdio.h>
#include <mapi.h>
LPMAPILOGON lpfnMAPILogon;
LPMAPISENDMAIL lpfnMAPISendMail;
LPMAPILOGOFF lpfnMAPILogoff;
MapiRecipDesc recipient =
{
0, MAPI_TO,
"Bill Clinton", "SMTP:president@whitehouse.gov",
0, NULL
};
MapiMessage message =
{
0, "Greetings",
"Hello, Mr. President!\n",
NULL, NULL, NULL, 0, NULL, 1, &recipient, 0, NULL
};
void main(void)
{
LHANDLE lhSession;
HANDLE hMAPILib;
hMAPILib = LoadLibrary("MAPI32.DLL");
lpfnMAPILogon =
(LPMAPILOGON)GetProcAddress(hMAPILib, "MAPILogon");
lpfnMAPISendMail =
(LPMAPISENDMAIL)GetProcAddress(hMAPILib, "MAPISendMail");
lpfnMAPILogoff =
(LPMAPILOGOFF)GetProcAddress(hMAPILib, "MAPILogoff");
(*lpfnMAPILogon)(0, NULL, NULL, MAPI_ALLOW_OTHERS, 0,
&lhSession);
(*lpfnMAPISendMail)(lhSession, 0, &message, 0, 0);
(*lpfnMAPILogoff)(lhSession, 0, 0, 0);
printf("Message to the White House sent.\n");
FreeLibrary(hMAPILib);
}
Simple MAPI can also be used to process incoming messages. Calls like
MAPIFindNext and MAPIReadMail can be used, for example, to examine new
messages in the user's Inbox.
Simple MAPI also offers a user interface for entering addresses. Instead of
using MAPISendDocuments, you can utilize the MAPIAddress call to enable the
user to select and enter addresses.
Common Messaging Calls
Common Messaging Calls is an implementation of the X.400 API Association's
Common Messaging Call API. It provides a series of high-level messaging
functions that can be used in a fashion similar to Simple MAPI.
Table 35.1 compares CMC functions with Simple MAPI functions.
Table 35.1. CMC and Simple MAPI.
CMC Simple MAPI Description
cmc_logon MAPILogon Log on to the service
cmc_logoff MAPILogoff Log off from the service
cmc_free MAPIFreeBuffer Free allocated memory
cmc_send MAPISendMail Send a message
cmc_send_documents MAPISendDocuments Send files in a message
cmc_list MAPIFindNext Find messages
cmc_read MAPIReadMail Retrieve messages
cmc_act_on MAPISaveMail
MAPIDeleteMail Save or delete messages
cmc_look_up MAPIAddress
MAPIDetails
MAPIResolveName Addressing
cmc_query_configurationN/A CMC configuration data
The program in Listing 35.3 demonstrates the use of CMC calls from within a
console application. You can compile and run this program from the command
line. To compile, use cl cmcmsg.c.
Listing 35.3. CMC in a console application.
#include <windows.h>
#include <xcmc.h>
typedef CMC_return_code (FAR PASCAL *LPFNCMCLOGON)(CMC_string,
CMC_string, CMC_string, CMC_enum, CMC_ui_id, CMC_uint16,
CMC_flags, CMC_session_id FAR *,CMC_extension FAR *);
typedef CMC_return_code (FAR PASCAL *LPFNCMCSEND)(CMC_session_id,
CMC_message FAR *, CMC_flags, CMC_ui_id,CMC_extension FAR *);
typedef CMC_return_code (FAR PASCAL *LPFNCMCLOGOFF)(CMC_session_id,
CMC_ui_id, CMC_flags, CMC_extension FAR *);
LPFNCMCLOGON lpfnCMCLogon;
LPFNCMCSEND lpfnCMCSend;
LPFNCMCLOGOFF lpfnCMCLogoff;
CMC_recipient recipient =
{
"Bill Clinton", CMC_TYPE_INDIVIDUAL,
"SMTP:president@whitehouse.gov", CMC_ROLE_TO,
CMC_RECIP_LAST_ELEMENT, NULL
};
CMC_message message =
{
NULL, "CMC: IPM", "Greetings", {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
"Hello, Mr. President!\n", &recipient, NULL,
CMC_MSG_LAST_ELEMENT, NULL
};
void main(void)
{
char msg[1000];
CMC_session_id session;
CMC_return_code retcode;
HANDLE hMAPILib;
hMAPILib = LoadLibrary("MAPI32.DLL");
lpfnCMCLogon =
(LPFNCMCLOGON)GetProcAddress(hMAPILib, "cmc_logon");
lpfnCMCSend =
(LPFNCMCSEND)GetProcAddress(hMAPILib, "cmc_send");
lpfnCMCLogoff =
(LPFNCMCLOGOFF)GetProcAddress(hMAPILib, "cmc_logoff");
(*lpfnCMCLogon)(NULL, NULL, NULL, (CMC_enum)0, 0, 100,
CMC_ERROR_UI_ALLOWED | CMC_LOGON_UI_ALLOWED, &session, NULL);
(*lpfnCMCSend)(session, &message, 0, 0, NULL);
(*lpfnCMCLogoff)(session, 0,
CMC_ERROR_UI_ALLOWED | CMC_LOGOFF_UI_ALLOWED, NULL);
printf("Message to the White House sent.\n");
FreeLibrary(hMAPILib);
}
Extended MAPI
Extended MAPI is a large, complex object-oriented programming interface to
all aspects of MAPI. Its programming model is based on OLE COM, the OLE
Component Object Model.
Extended MAPI defines a series of object types, including messages, message
stores, folders, attachments, mail users, address books, providers,
sessions, and many more supplementary objects. MAPI objects are
characterized by a set of properties, themselves implemented as objects.
MAPI objects are accessed through interfaces derived from the OLE IUnknown
interface. For example, property objects implement the IMAPIProp interface,
while message objects implement the IMessage interface.
Extended MAPI programming involves manipulating MAPI objects through their
properties and methods and through event notifications. MAPI properties can
be manipulated through property objects and the IMAPIProp interface, or
through property tables. Methods are the IUnknown-derived interfaces that
MAPI objects provide. Event notification is the mechanism of communication
between MAPI objects.
Extended MAPI can be used to implement messaging-based applications that
require finer control over messaging services than what is available
through Simple MAPI or CMC. Extended MAPI can also be used to perform
administrative functions, such as selecting and configuring services and
creating user profiles.
Another use of Extended MAPI is to program with MAPI forms. MAPI forms
represent special types of messages, implemented through a user interface
and a form server, which manage the user's interaction with the forms
message.
Extended MAPI can also be used to extend the Microsoft Exchange client.
Customized versions of the Microsoft Exchange client can provide
application-specific views on address books, message stores, and message
objects, and can add new searching, addressing, and workgroup features to
that application.
Lastly, Extended MAPI also represents the programming interface for
creating MAPI service providers. These include address books, message
stores, and transports.
OLE Messaging
OLE messaging exposes MAPI objects through the OLE automation interface. As
such, it works best with OLE automation clients, such as Visual Basic
applications or programs written in Visual Basic for Applications (that is,
Microsoft Excel, Access, or Project programs).
Figure 35.3 illustrates the hierarchy of OLE automation objects exposed by
OLE messaging.
Figure 35.3. OLE messaging objects.
Demonstrating the use of OLE messaging from within Visual C++ is difficult,
as it requires constructing an OLE automation client application. In order
to demonstrate a simple OLE messaging session, I decided to resort to
Visual Basic. The example shown in Listing 35.4 shows how a Visual Basic
application can send a simple message without displaying a user interface.
Listing 35.4. OLE messaging example in Visual Basic.
Sub Command1_Click ()
Dim objSession As Object
Dim objMessage As Object
Dim objRecip As Object
Set objSession = CreateObject("MAPI.Session")
objSession.Logon "", "", False, False
Set objMessage = objSession.Outbox.Messages.Add
objMessage.Subject = "Greetings"
objMessage.Text = "Hello again, Mr. President!"
Set objRecip = objMessage.Recipients.Add
objRecip.Name = "Bill Clinton"
objRecip.Address = "SMTP:president@whitehouse.gov"
objRecip.Type = 1
objRecip.Resolve (False)
objMessage.Send True, False
MsgBox "Message to the White House sent"
objSession.Logoff
Exit Sub
End Sub
To test this simple example, attach this code to a button in a Visual Basic
form (you can also use disptest.exe, the OLE automation test version of
Visual Basic that came as part of your Visual C++ installation), run the
program, and click on the button. Oh, and don't forget to change the
address before exercising this code!
Note that this test will only work if you have OLE messaging installed on
your computer. OLE messaging components are only available at present as
part of the MAPI SDK, distributed through the Microsoft Developer Network
level 2 subscription.
MAPI Support in MFC
The Microsoft Foundation Classes Library provides MAPI support through a
series of member functions in CDocument. This support, and how this support
is incorporated into MFC framework applications, is the subject of the last
part of this chapter.
MAPI Support in CDocument
The CDocument class supports MAPI through the OnFileSendMail member
function.
CDocument::OnFileSendMail serializes the document into a temporary file,
and then calls Simple MAPI functions to prepare and send a message with
this file as an attachment.
A variant of CDocument::OnFileSendMail is COleDocument::OnFileSendMail;
this version handles compound files correctly.
The CDocument::OnUpdateFileSendMail member function determines whether MAPI
support is available on the system and updates command items accordingly
through a CCmdUI object.
MAPI and AppWizard
The AppWizard can generate skeleton applications with minimal MAPI support.
If requested, the AppWizard will add a Send menu item to the new
application's File menu. This item will invoke the OnFileSendMail member
function of the application's document class. AppWizard will also install a
command update handler, referencing the OnUpdateFileSendMail member
function.
In other words, if you only wish to make your application messaging-aware,
you need not do anything other than enabling MAPI support when creating the
application's skeleton with AppWizard. This is all you need to do in order
to satisfy the new Windows 95 Logo requirements.
Summary
MAPI, the Messaging Application Programming Interface, represents a
comprehensive set of specifications that link messaging applications on the
one hand and messaging service providers on the other, forming a messaging
architecture.
Messaging applications include messaging-aware, messaging-enabled, and
messaging-based programs. Messaging-aware applications such as the Windows
95 WordPad, although they provide some level of MAPI functionality, do not
depend on the presence of MAPI for their functionality. Messaging-enabled
applications such as Microsoft Schedule+ require the presence of MAPI to
perform many of their functions. Messaging-based applications such as the
Microsoft Exchange client require MAPI in order to function.
On the service provider side, MAPI recognizes message stores, address
books, and transport providers. These providers, acting under the control
of the MAPI Spooler, perform the services that together form the messaging
system on your computer.
The MAPI configuration is stored in the form of MAPI profiles. MAPI
profiles are registry entries that identify active MAPI services and their
configuration. A user can have several MAPI profiles, with an active
profile selected at the start of the MAPI session.
When developing MAPI applications, one can pick one of several APIs. Simple
MAPI provides a set of functions essential for addressing sending simple
messages and retrieving incoming messages. Similar functionality is offered
by CMC, the Common Messaging Call API; however, CMC is completely
platform-independent. CMC is an implementation of the X.400 API
Association's Common Messaging Call API. Visual Basic and Visual C++
applications can also use OLE Messaging for an object-oriented interface to
MAPI functions.
The full interface to MAPI, Extended MAPI, is used for developing
messaging-based applications, service providers, new message types (MAPI
forms), administrative applications, and extensions to the Microsoft
Exchange client application.
--
¡ù À´Ô´:¡¤¹þ¶û±õ×϶¡ÏãÕ¾ bbs1.hit.edu.cn¡¤[FROM: crystal.bbs@bbs.net.]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
Ò³ÃæÖ´ÐÐʱ¼ä£º415.289ºÁÃë