Simple MAPI
A. First Edition
This is just a joke! Wang Hui developed a software tool for managing Outlook Express and sold for some money. And I am not
very happy about this. Also to satisfy my heart, we have a bet. If I can just read a single message from local mail box, he
will eat up my keyboard or displayer, provided I give him some sauce to make things easier!
So, this is a simple program of reading OE and I only finished it within a couple of hours to win my bet.
B.The problem
The thing is like this. MAPI is a rather general protocol not only for MS. Therefore you can find that MAPI.dll or
MAPI32.dll all support them. However, as a free software, should Outlook Express support them? According to Wang Hui,
Microsoft hates OE because it is free with windows and it already becomes the biggest competitor for its Outlook. Hence,
MS even removes programmers from OE group to stop upgrading it.
And the key of the all this is that OE does support MAPI. However, MAPI doesn't specify how local mails should be handled.
It is really up to mail client to handle. And MS also doesn't like people to know the structure of storage. My personal
opinion is that the best of what MS can do is using OLE store. But it may not be efficient and MS doesn't like people feel
too easy to develop application for OE. Instead MS hopes programmer can work more for Outlook.
The above question has a bad solution to do it. You can rename the "Inbox.dbx" file to some other name and rename other
mail box file to "Inbox.dbx". Then you can use the "findnext" and "readmail", "savemail" etc. Later you can change back
their name.
Another problem is that I directly load library of "msoe.dll" instead of "mapi32.dll" or "mapi.dll". Probably this is not
the best way if people are not actually using OE. But as I explained above, this is just a joke.
D.The major functions
I suspect the implementation of "findnext" is not implemented efficiently because it is like searching every time from
beginning link list or table.
Please note that in my project file, I output the executable file to the directory "C:\Program Files\Outlook Express".
E.Further improvement
F.File listing
1. mapi.cpp
กก
file name: mapi.cpp
// mapi.cpp : Defines the entry point for the application. // #include <basetsd.h> #include <stdio.h> #include <windows.h> #include <mapi.h> //#define ULONG unsigned long; //typedef unsigned long ULONG; typedef ULONG (FAR PASCAL *MAPIFreeBufferType)( LPVOID pv ); typedef ULONG (FAR PASCAL *MAPILogonType) ( ULONG ulUIParam, LPTSTR lpszProfileName, LPTSTR lpszPassword, FLAGS flFlags, ULONG ulReserved, LPLHANDLE lplhSession ); typedef ULONG (FAR PASCAL *MAPIReadMailType)( LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageID, FLAGS flFlags, ULONG ulReserved, lpMapiMessage FAR * lppMessage ); typedef ULONG (FAR PASCAL *MAPIFindNextType)( LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageType, LPTSTR lpszSeedMessageID, FLAGS flFlags, ULONG ulReserved, LPTSTR lpszMessageID ); typedef ULONG (FAR PASCAL *MAPILogoffType) ( LHANDLE lhSession, ULONG ulUIParam, FLAGS flFlags, ULONG ulReserved ); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { FILE* stream; MAPILogonType mapiLogon; MAPIReadMailType mapiReadMail; MAPIFindNextType mapiFindNext; MAPIFreeBufferType mapiFreeBuffer; MAPILogoffType mapiLogoff; ULONG result; ULONG session; HMODULE hmodule; lpMapiMessage mapiMsg; char buffer[512]; if ((hmodule=LoadLibrary("msoe.dll"))==NULL) { printf("failed\n"); exit(1); } if ((mapiLogon=(MAPILogonType)(GetProcAddress(hmodule, "MAPILogon")))==NULL) { printf("failed getprocaddress\n"); exit(2); } if ((mapiReadMail=(MAPIReadMailType)(GetProcAddress(hmodule, "MAPIReadMail")))==NULL) { printf("failed getprocaddress\n"); exit(2); } if ((mapiFindNext=(MAPIFindNextType)(GetProcAddress(hmodule, "MAPIFindNext")))==NULL) { printf("failed getprocaddress\n"); exit(2); } if ((mapiFreeBuffer=(MAPIFreeBufferType)(GetProcAddress(hmodule, "MAPIFreeBuffer")))==NULL) { printf("failed getprocaddress\n"); exit(2); } if ((mapiLogoff=(MAPILogoffType)(GetProcAddress(hmodule, "MAPILogoff")))==NULL) { printf("failed getprocaddress\n"); exit(2); } if ((result=mapiLogon((ULONG)hInstance, NULL, NULL, MAPI_NEW_SESSION|MAPI_LOGON_UI, 0, &session)) !=SUCCESS_SUCCESS) { switch (result) { case MAPI_E_FAILURE: printf("One or more unspecified errors occurred during logon. No session handle was returned."); break; case MAPI_E_INSUFFICIENT_MEMORY: printf("There was insufficient memory to proceed. No session handle was returned. "); break; case MAPI_E_LOGIN_FAILURE: printf("There was no default logon, and the user failed to log on successfully\ when the logon dialog box was displayed. No session handle was returned. "); break; case MAPI_E_TOO_MANY_SESSIONS: printf("The user had too many sessions open simultaneously. No session handle was returned. "); break; case MAPI_E_USER_ABORT: printf("The user canceled the logon dialog box. No session handle was returned. "); break; } exit(3); } bool stop=false; stream=fopen("subject.txt", "w"); char* ptr=NULL; char* msgType="anything"; while (true) { if ((result=mapiFindNext(session, (ULONG)hInstance, msgType, ptr, MAPI_LONG_MSGID|MAPI_GUARANTEE_FIFO, 0, buffer))!=SUCCESS_SUCCESS) { switch (result) { case MAPI_E_FAILURE: printf("One or more unspecified errors occurred while matching the message type. \ The call failed before message type matching could take place. "); break; case MAPI_E_INSUFFICIENT_MEMORY : printf("There was insufficient memory to proceed. No message was found. "); break; case MAPI_E_INVALID_MESSAGE : printf("An invalid message identifier was passed in the lpszSeedMessageID parameter.\ No message was found. "); break; case MAPI_E_INVALID_SESSION : printf("An invalid session handle was passed in the lhSession parameter. No message was found. "); break; case MAPI_E_NO_MESSAGES : printf("A matching message could not be found. "); stop=true; break; } } ptr=buffer; if (stop) { fclose(stream); if ((result=mapiLogoff(session, (ULONG)hInstance, 0, 0))!=SUCCESS_SUCCESS) { switch (result) { case MAPI_E_FAILURE : printf("The flFlags parameter is invalid or one or more unspecified \ errors occurred. "); break; case MAPI_E_INSUFFICIENT_MEMORY : printf("There was insufficient memory to proceed. \ The session was not terminated. "); break; case MAPI_E_INVALID_SESSION : printf("An invalid session handle was used for the lhSession parameter. \ The session was not terminated."); break; } exit(6); } break; } if ((result=mapiReadMail(session, (ULONG)hInstance, buffer, MAPI_ENVELOPE_ONLY, 0, &mapiMsg)) !=SUCCESS_SUCCESS) { switch (result) { case MAPI_E_ATTACHMENT_WRITE_FAILURE : printf("An attachment could not be written to a temporary file. Check directory permissions. "); break; case MAPI_E_DISK_FULL : printf("An attachment could not be written to a temporary file because there was not \ enough space on the disk. "); break; case MAPI_E_FAILURE: printf("One or more unspecified errors occurred while reading the message. "); break; case MAPI_E_INSUFFICIENT_MEMORY : printf("There was insufficient memory to read the message. "); break; case MAPI_E_INVALID_MESSAGE : printf("An invalid message identifier was passed in the lpszMessageID parameter. "); break; case MAPI_E_INVALID_SESSION : printf("An invalid session handle was passed in the lhSession parameter. No message was retrieved. "); break; case MAPI_E_TOO_MANY_FILES : printf("There were too many file attachments in the message. The message could not be read. "); break; case MAPI_E_TOO_MANY_RECIPIENTS : printf("There were too many recipients of the message. The message could not be read. "); break; } } fprintf(stream, "id: %s; subject:%s\n", buffer, mapiMsg->lpszSubject); if ((result=mapiFreeBuffer((void*)mapiMsg))!=SUCCESS_SUCCESS) { if (result==MAPI_E_FAILURE) { printf("One or more unspecified errors occurred. The memory could not be freed. "); exit(4); } } } FreeLibrary(hmodule); return 0; }
กก
กก