Click here to Skip to main content
Licence 
First Posted 24 Sep 2001
Views 347,940
Bookmarked 75 times

Sending and receiving e-mails from your program

By | 5 Nov 2002 | Article
A simple reusable MAPI client

Introduction

" MAPI is a set of functions that mail-enabled and mail-aware applications use to create, manipulate, transfer, and store mail messages. It gives application developers the tools to define the purpose and content of mail messages, and gives them flexibility in their management of stored mail messages. MAPI also provides a common interface that application developers can use to create mail-enabled and mail-aware applications independent of the underlying messaging system. "  --- Quoted from MSDN.

I am not an expert on either MAPI or e-mail in general.  I found that using MAPI functions is not exactly easy.  What I need is a simple reusable component that provides simple e-mail functionality to all of my programs on the Win32 platforms.  For example, when a serious error occurs in my system, I want an e-mail message to be sent to a list administrators, I also want the same to be done when our servers are about to run out of virtual memory.  Some of my server programs also have to process e-mails (read messages from the inbox and call various services accordingly).

But I was too lazy to sit down and learn all the MAPI functions.  Fortunately, there is an ActiveX control MSMAPI32.ocx from Microsoft, which comes with VC++ and other MS products.  I don't really like the way this control works, and most importantly I want to make things easier, so I wrote a com component XYMail.dll which uses this control to provide simple e-mail functionality. You can use and modify the source code anyway you wish, but give me some credit if possible (please? :-).

XYMailClient

XYMailClient is a com object implemented in XYMail.dll.  It provides the following thread-safe methods:

BOOL InitSession(BSTR strProfile, BSTR strPassword);
This method is called to establish a MAPI session with the mail server.  The strProfile parameter is the name of an e-mail profile for the current user, and strPassword is the password (use empty string if there is no password).  The established session is global to the process.  That is, the established session is available to all the other XYMailClient objects in the same process until the EndSession method is called.  The return value indicates whether the operation is successful.  In case of error, a trace message will be written to the XYMail.log file in the current working directory.

BOOL SendMsg(BSTR strTo, BSTR strCc, BSTR strBcc, BSTR strTitle, BSTR strText, BSTR strAttachment);
Call this method to send an e-mail message to the recipients specified by the arguments.  The strTo, strCc, and strBcc are all lists of semi-colon delimited e-mail addresses.  The strTitle parameter is the message subject, and strText is the message body.  The strAttachment parameter is a semi-colon delimited list of full path names for attachment files.  The return value indicates whether the operation is successful.  In case of error, a trace message will be written to the XYMail.log file in the current working directory.

long FetchMsg();
Call this method to fetch all in-coming messages from the mail server.  The return value is the total number of messages in the inbox.  In case of error, the return value will be -1 and  a trace message will be written to the XYMail.log file in the current working directory.

BSTR GetMsg(long nIndex);
Call this method to retrieve the message in the inbox with the given (zero-based) index.  The returned value is a string of the following format:

<XYMail><Sender>...</Sender><Title>...</Title><Text>...</Text><br>
   <Attachment>...</Attachment><Received>...</Received></XYMail>

The fields within this string packet can be extracted using the ExtractValue method.  If there is no such message, the return value will be the empty string and a trace message will be written to the XYMail.log file in the current working directory.

void DeleteMsg(long nIndex);
Call this method to delete the message from the inbox with the given (zero-based) index.  If nIndex is -1, then all messages will be deleted. Note that if you want to delete multiple messages using this method, you need to go from higher index to lower index because deleting a message with lower index first will change indices of remaining messages.

BSTR ExtractValue(BSTR strField, BSTR strDataPacket);
Call this method to extract a message field from the input string packet.  The strDataPacket parameter is the return value of a previous call to the GetMsg method and strField can be one of the following strings: "Sender", "Title", "Text", "Attachment", "Received". 

void EndSession();
Call this method to terminate the current MAPI session.  Note that the MAPI session is global to the process and this method affects all XYMailClient objects within the same process.

Sample code

Here is a complete C++ console application that demonstrates the e-mail functions using XYMailClient.  The header file XYMailClientWrapper.h is included with the source code, it declares a wrapper class for XYMailClient.
/*************** Test.cpp ***********************/

#include "XYMailClientWrapper.h"
#include <stdio.h>

void main()
{
    // declare the wrapper class object
    XYMailClientWrapper xyMail;    

    // call InitSession
    xyMail.InitSession("MyProfileName","");    

    // send a test message to guy@aol.com and girl@aol.com,
    // cc to ok@aol.com,
    // bcc to hey@aol.com
    xyMail.SendMsg("guy@aol.com;girl@aol.com","ok@aol.com","<a href="mailto:hey@aol.com">hey@aol.com</a>",
                   "Test","A test","<a href="file:///c://test1.txt;c://test2.txt">c:\\test1.txt;c:\\test2.txt</a>"));    

    // fetch messages
    printf("Total messages: %d\n",xyMail.FetchMsg());    

    // retrieve the first message
    _bstr_t strMsg = xyMail.GetMsg(0);    

    // printing various fields in the retrieved message
    printf("Sender: %s\n",(char *)xyMail.ExtractValue("Sender",strMsg));
    printf("Title: %s\n",(char *)xyMail.ExtractValue("Title",strMsg));
    printf("Text: %s\n",(char *)xyMail.ExtractValue("Text",strMsg));
    printf("Attachment: %s\n",(char *)xyMail.ExtractValue("Attachment",strMsg));
    printf("Received: %s\n",(char *)xyMail.ExtractValue("Received",strMsg));    

    // delete second and first messages
    xyMail.DeleteMsg(1);
    xyMail.DeleteMsg(0);    

    // delete all messages and end the session
    xyMail.DeleteMsg(-1);
    xyMail.EndSession();
}
/**************** End of Test.cpp ****************/

Here is a VB script file that does almost exactly the same things as the above C++ program:

'**************** Test.vbs ********************
dim obj
set obj = CreateObject("XYMailClient.1")

obj.InitSession("MyProfileName", "")
obj.SendMsg("guy@aol.com;girl@aol.com","ok@aol.com","<a href="mailto:hey@aol.com">hey@aol.com</a>",
            "Test","A test","c:\\test1.txt;c:\\test2.txt"));

WScript.echo obj.FetchMsg()

dim strMsg
strMsg = obj.GetMsg(0)

WScript.echo obj.ExtractValue("Sender", strMsg)
WScript.echo obj.ExtractValue("Title", strMsg)
WScript.echo obj.ExtractValue("Text", strMsg)
WScript.echo obj.ExtractValue("Attachment", strMsg)
WScript.echo obj.ExtractValue("Received", strMsg)

obj.DeleteMsg(1)
obj.DeleteMsg(0)
obj.DeleteMsg(-1)
obj.EndSession()

set obj = Nothing

'**************** End of Test.vbs **************

Using XYMailClient in your own program

XYMailClient is implemented with VC++ 5.0 using ATL and MFC.  In case you are interested in implementation details, you need only to read one source file XYMailClient.cpp, all the other files in the project are generated by the AppWizard.

To install XYMailClient, you need to copy XYMail.dll onto your machine and register it.  However, XYMailClient depends on MSMAPI32.ocx so you need to install that, too (most machines already have it).  You also have to configure an e-mail profile before using XYMailClient.  You can use the Mail icon in the control panel to configure it (you already did this if MS Outlook is currently working on your machine).

For your convenience, I have included a header file XYMailClientWrapper.h, which contains a C++ wrapper class.  To use XYMailClient in a C++ program, you need only to do the following: include this header file, declare a XYMailClientWrapper object, and call its methods.  A known problem on using XYMailClient in a C++ console application is that you must call the EndSession method before terminating your program, otherwise your program will crash.

If you try to use XYMailClient within an NT service or within a process created by an NT service, you may not be able to call InitSession successfully.  This is because the NT service may be running under the default system account, which has no e-mail profile.  You can configure an NT service to run under a regular user account so that an e-mail profile is available.  This will solve the problem in most cases.

Thank you for reading this article.  Please visit my home page for my other articles and programs.

History

12 Mar 2002 - updated source

6 Nov 2002 - updated source

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Xiangyang Liu 刘向阳



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMFC AppWizard (exe) Pinmemberkip_chuko17:11 30 May '11  
QuestionWhy the stupid popup dialog hack? Pinmembermnbv09876:10 15 Sep '09  
QuestionLogin has failed [modified] PinmemberSingKyo6:25 19 Mar '08  
GeneralGet the sender email address PinmemberY G15:43 21 Dec '05  
GeneralMissing XYMapi.h file. PinmemberWade Pierce14:35 9 Dec '05  
GeneralRe: Missing XYMapi.h file. PinmemberXiangyang Liu15:44 9 Dec '05  
QuestionHow can i make mail profile on Windows XP? PinsussAnonymous3:34 12 Oct '05  
GeneralSending e-mail as.. PinmemberAlexEvans19:53 3 Oct '05  
GeneralMsg stay in Outbox using Outlook 2003 Pinmembersilygose9:11 30 Jun '05  
GeneralRe: Msg stay in Outbox using Outlook 2003 PinmemberGautam Jain3:43 17 Nov '06  
GeneralLINK : fatal error LNK1104: cannot open file "mfc42u.lib" Pinmembertrissanen@hotmail.com2:10 23 Mar '05  
GeneralRe: LINK : fatal error LNK1104: cannot open file "mfc42u.lib" PinmemberXiangyang Liu7:29 23 Mar '05  
GeneralDoes it support any Email Client Pinmemberanoopmys19:55 21 Mar '05  
GeneralInvalid Class String creating MAPI.Session Pinmembersilygose10:02 19 Jan '05  
GeneralRe: Invalid Class String creating MAPI.Session PinmemberXiangyang Liu13:58 19 Jan '05  
GeneralRe: Invalid Class String creating MAPI.Session Pinmembersilygose5:39 20 Jan '05  
GeneralRe: Invalid Class String creating MAPI.Session Pinmemberslimstickey7:34 17 Jan '06  
QuestionDeleting mails don't change the .pst files size ?? Pinmember_kane_19:42 11 Dec '04  
AnswerRe: Deleting mails don't change the .pst files size ?? Pinmembersanjaylk3:15 4 Mar '06  
GeneralRe: Deleting mails don't change the .pst files size ?? Pinmember_kane_3:16 4 Mar '06  
GeneralNo need to login ? ! Pinmember_kane_20:16 7 Oct '04  
GeneralRe: No need to login ? ! PinmemberXiangyang Liu23:13 7 Oct '04  
GeneralRe: No need to login ? ! Pinmember_kane_1:55 8 Oct '04  
GeneralRe: No need to login ? ! PinmemberXiangyang Liu2:39 8 Oct '04  
GeneralRe: No need to login ? ! Pinmembermnbv09876:09 15 Sep '09  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120517.1 | Last Updated 6 Nov 2002
Article Copyright 2001 by Xiangyang Liu 刘向阳
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid