Important: |
---|
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. |
New messages are created and sent from a message store's Draftsfolder. After you create a message, you set its property values (subject, body, list of recipients, and so on) and then post the message.
To send a message
-
Initialize the MAPI subsystem, and log onto a MAPI session. For more information, see Beginning a MAPI Session.
-
Establish a connection to a message store. For more information, see Connecting to a Message Store.
-
Create a message object. For more information, see Creating a Message.
-
Prepare and set the list of recipients for the message. Typically, there are three properties to set for each recipient: PR_RECIPIENT_TYPE, PR_ADDRTYPE, and PR_EMAIL_ADDRESS.
- Allocate memory for the list of recipients by calling
MAPIAllocateBufferwith the total size of the recipient list.
Copy Code ULONG cRecipients = 1; // Send a message to one recipient. LPWSTR pszTo = L"you@mycompany.com"; // The e-mail address of the recipient. ULONG cRecipientProperties = 3; // Set three properties for the recipient. LPADRLIST pRecipientList = NULL; ULONG cbRecipientList = 0; cbRecipientList = sizeof(ADRLIST) + cRecipients * (sizeof(ADRENTRY) + cRecipientProperties * (sizeof(SPropValue) + (wcslen(pszTo)+3) * sizeof(WCHAR))); hr = MAPIAllocateBuffer(cbRecipientList, (LPVOID FAR *)&pRecipientList);
- Initialize the recipient list by using
memset to set the entire buffer to 0, and then begin filling-in values for the recipient list.
Copy Code memset(pRecipientList, 0, cbRecipientList); pRecipientList->cEntries = cRecipients; pRecipientList->aEntries[0].cValues = cRecipientProperties;
- Initialize the array of recipient properties.
Copy Code int cbRecipientProperties = 0; cbRecipientProperties = cRecipientProperties * sizeof(SPropValue); hr = MAPIAllocateBuffer(cbRecipientProperties, (LPVOID FAR *)&pRecipientList->aEntries[0].rgPropVals); memset(pRecipientList->aEntries[0].rgPropVals, 0, sizeof(SPropValue) * 3);
- Set the recipient type property value to indicate whether the
recipient is listed on the
To:,
Cc:, or
Bcc: fields by using the
PR_RECIPIENT_TYPEproperty. This is the first of three
properties that are being set in the recipient list.
Copy Code pRecipientList->aEntries[0].rgPropVals[0].ulPropTag = PR_RECIPIENT_TYPE; pRecipientList->aEntries[0].rgPropVals[0].Value. ul = MAPI_TO;
- Set the address type property value to SMTP by using the
PR_ADDRTYPEproperty. This is the second of three properties
that are being set in the recipient list.
Copy Code pRecipientList->aEntries[0].rgPropVals[1].ulPropTag = PR_ADDRTYPE; pRecipientList->aEntries[0].rgPropVals[1].Value.lpszW = L"SMTP";
- Set the e-mail address for each message recipient by using the
PR_EMAIL_ADDRESSproperty. This is the third and final property
that is being set in the recipient list.
Copy Code pRecipientList->aEntries[0].rgPropVals[2].ulPropTag = PR_EMAIL_ADDRESS; pRecipientList->aEntries[0].rgPropVals[2].Value.lpszW = pszTo;
- Add the list of recipients to your message by calling the
IMessage::ModifyRecipientsmethod with the
MODRECIP_ADDflag.
Copy Code hr = pMsg->ModifyRecipients(MODRECIP_ADD, pRecipientList);
- Free the memory resources taken by the Drafts Folder by calling
MAPI
IUnknown::Release, and by the list of recipients by calling
MAPIFreeBuffer.
Copy Code hr = pFldrDrafts->Release(); pFldrDrafts = NULL; hr = MAPIFreeBuffer(pRecipientList->aEntries[0].rgPropVals); hr = MAPIFreeBuffer(pRecipientList);
- Allocate memory for the list of recipients by calling
MAPIAllocateBufferwith the total size of the recipient list.
-
Prepare and set the following properties of the message: PR_MSG_STATUS, PR_MESSAGE_FLAGS, and PR_SUBJECT.
- Allocate memory for the message property array by calling
MAPIAllocateBufferwith the total size of the message
properties. To find out how many bytes of memory the properties
will require, add the size of the
SPropTagArraydata type, to the size of four
SPropValuestructure (one for each property), and then add the
number of characters in the subject line, multiplied by the number
of bytes taken be each of its UNICODE characters.
Copy Code LPSPropValue rgpMsgProperties = NULL; // A pointer to the property value structure. int cbMsgProperties = 0; // The size, in bytes, of the properties. int cMsgProperties = 4; // The number of properties. LPWSTR pszSubject = L"This is only a MAPI Text Message"; cbMsgProperties = sizeof(SPropTagArray) + cMsgProperties * (sizeof(SPropValue) + (wcslen(pszSubject) + 3) * sizeof(WCHAR)); hr = MAPIAllocateBuffer(cbMsgProperties, (LPVOID FAR *)&rgpMsgProperties);
- Initialize the message property array by using
memset to set the entire buffer to 0.
Copy Code memset(rgpMsgProperties, 0, cbMsgProperties);
- Set the message's subject by setting the
PR_SUBJECTproperty to a value of
pszSubject.
Copy Code rgpMsgProperties[0].ulPropTag = PR_SUBJECT; rgpMsgProperties[0].Value.lpszW = pszSubject;
- Set a couple flags on the message by setting the
PR_MESSAGE_FLAGSproperty to the bitmask value
MSGFLAG_UNSENTand
MSGFLAG_FROMME.
Copy Code rgpMsgProperties[1].ulPropTag = PR_MESSAGE_FLAGS; rgpMsgProperties[1].Value.ul = MSGFLAG_FROMME | MSGFLAG_UNSENT; // Notice how to combine multiple flags.
- Tag the message to identify that it is intended to be received
as an SMTP message (as opposed to SMS) by setting the
PR_MSG_STATUSproperty to a value of
MSGSTATUS_RECTYPE_SMTP.
Copy Code rgpMsgProperties[2].ulPropTag = PR_MSG_STATUS; rgpMsgProperties[2].Value.ul = MSGSTATUS_RECTYPE_SMTP;
- Set the message's importance level to High by setting the
PR_IMPORTANCEproperty to a value of
IMPORTANCE_HIGH.
Copy Code rgpMsgProperties[3].ulPropTag = PR_IMPORTANCE; rgpMsgProperties[3].Value.ul = IMPORTANCE_HIGH;
- Add the array of properties to the message by calling the
IMAPIProp::SetPropsmethod on the
IMessageobject.
Copy Code hr = pMsg->SetProps(cMsgProperties, rgpMsgProperties, NULL);
- Free the memory buffer for the message property array by
calling
MAPIFreeBuffer.
Copy Code hr = MAPIFreeBuffer(rgpMsgProperties);
- Allocate memory for the message property array by calling
MAPIAllocateBufferwith the total size of the message
properties. To find out how many bytes of memory the properties
will require, add the size of the
SPropTagArraydata type, to the size of four
SPropValuestructure (one for each property), and then add the
number of characters in the subject line, multiplied by the number
of bytes taken be each of its UNICODE characters.
-
Prepare and write the text body of the message.
- Declare a
NULL
IStreaminterface object, and then call the
IMAPIProp::OpenPropertymethod of the
IMessageobject to get a reference to the message body text
stream.
Copy Code LPSTREAM pStream = NULL; hr = pMsg->OpenProperty(PR_BODY, NULL, 0, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN *)&pStream);
- Write text to the body of the message by calling the
IStream::Writemethod of the
IStreamobject.
Copy Code LPWSTR pszBody = L"This text belongs to the body of the message."; ULONG cbBody = 0; ULONG cbWritten = 0; cbBody = (wcslen(pszBody) + 1) * sizeof(WCHAR); hr = pStream-> Write(pszBody, cbBody, &cbWritten);
- If it is no longer needed, release the
IStreamobject by calling
MAPI
IUnknown::Releaseon it.
Copy Code pStream-> Release(); pStream = NULL;
- Declare a
NULL
IStreaminterface object, and then call the
IMAPIProp::OpenPropertymethod of the
IMessageobject to get a reference to the message body text
stream.
-
Submit the message by calling the IMessage::SubmitMessagemethod of the IMessageobject.
Copy Code hr = pMsg-> SubmitMessage(0);
-
If it is no longer needed, release the IMessageobject by calling MAPI IUnknown::Releaseon it.
Copy Code pMsg-> Release(); pMsg = NULL;
Example
The following code example is a function that encapsulates the entire set of programmatic steps necessary to send an e-mail message from a Windows Mobile device.
Note: |
---|
To make the following code example easier to read, security checking and error handling are not included. This code example should not be used in a release configuration unless it has been modified to include them. |
Copy Code | |
---|---|
void MessagingApp(void) { ICEMAPISession * pSession = NULL; IMsgStore * pMsgStrore = NULL; IMessage * pMsg = NULL; IMAPITable * pTable = NULL; SRowSet * pSRowSet = NULL; IMAPIFolder * pFldrDrafts = NULL; ULONG rgTags[] = { 1, {PR_CE_IPM_DRAFTS_ENTRYID} }; LPSPropValue rgProps = NULL; ULONG cValues = 0; hr = MAPIInitialize(NULL); // Initialize the MAPI COM server. hr = MAPILogonEx(0, NULL, NULL, 0, (LPMAPISESSION *)&pSession); // Logon and get a Session pointer. hr = pSession->GetMsgStoresTable(0, &pTable); // Get a pointer to Message Store table (Accounts collection). hr = pTable->QueryRows(1, 0, &pSRowSet); // Get a pointer to the first row, which contains all the // properties of the first Message Store. // Get the message store's Entry ID. hr = pSession->OpenMsgStore(0, pSRowSet->aRow[0].lpProps[0].Value.bin.cb, (ENTRYID *)pSRowSet->aRow[0].lpProps[0].Value.bin.lpb, NULL, 0, &pMsgStrore); // Get the Drafts Folder's Entry ID. hr = pMsgStrore->GetProps((LPSPropTagArray)rgTags, MAPI_UNICODE, &cValues, &rgProps); // Get a handle to the Drafts Folder. hr = pMsgStrore->OpenEntry(rgProps[0].Value.bin.cb, (LPENTRYID)rgProps[0].Value.bin.lpb, NULL, MAPI_MODIFY, NULL, (LPUNKNOWN*)&pFldrDrafts); // Create a new Message object in the Drafts folder. hr = pFldrDrafts->CreateMessage(NULL, 0, &pMsg); // Setup the Recipient List. int cRecipients = 1; // Count of the number of Recipients. Sending to only one person. int cRecipientProperties = 3; // Count of properties for each Recipient. int nRecipientIndex = 0; WCHAR * pszTo = L"someone@microsoft.com"; // Address of Recipient. ADRLIST * pRecipientList = NULL; // List of Recipients, stored in an Address List. // This can be a semi-colon separated list. int cbRecipientList = 0; // The size of the Recipient List, in bytes. cbRecipientList = sizeof(ADRLIST) + cRecipients * (sizeof(ADRENTRY) + cRecipientProperties * (sizeof(SPropValue) + (wcslen(pszTo) + 3) * sizeof(WCHAR))); // Allocate memory for the Address List. hr = MAPIAllocateBuffer(cbRecipientList, (LPVOID FAR *)&pRecipientList); memset(pRecipientList, 0, cbRecipientList); pRecipientList->cEntries = cRecipients; pRecipientList->aEntries[0].cValues = cRecipientProperties; // The size of the array of Recipient properties, in bytes. int cbRecipientProperties = 0; cbRecipientProperties = cRecipientProperties * sizeof(SPropValue); hr = MAPIAllocateBuffer(cbRecipientProperties, (LPVOID FAR *)&pRecipientList->aEntries[nRecipientIndex].rgPropVals); memset(pRecipientList->aEntries[nRecipientIndex].rgPropVals, 0, sizeof(SPropValue) * 3); pRecipientList->aEntries[nRecipientIndex].cValues = cRecipientProperties; pRecipientList->aEntries[nRecipientIndex].rgPropVals[0].ulPropTag = PR_RECIPIENT_TYPE; pRecipientList->aEntries[nRecipientIndex].rgPropVals[0].Value.ul = MAPI_TO; pRecipientList->aEntries[nRecipientIndex].rgPropVals[1].ulPropTag = PR_ADDRTYPE; pRecipientList->aEntries[nRecipientIndex].rgPropVals[1].Value.LPSZ = TEXT("SMTP"); pRecipientList->aEntries[nRecipientIndex].rgPropVals[2].ulPropTag = PR_EMAIL_ADDRESS; pRecipientList->aEntries[nRecipientIndex].rgPropVals[2].Value.LPSZ = pszTo; hr = pMsg->ModifyRecipients(MODRECIP_ADD, pRecipientList); // Add the Recipients List to the message. hr = pFldrDrafts->Release(); pFldrDrafts = NULL; hr = MAPIFreeBuffer(pRecipientList->aEntries[nRecipientIndex].rgPropVals); hr = MAPIFreeBuffer(pRecipientList); // Setup the message's properties. LPSPropValue rgpMsgProperties = NULL; // An array of properties. int cbMsgProperties = 0; // The size of the array of properties. int cMsgProperties = 4; // The number of properties for the message. LPWSTR pszSubject = L"This is only a MAPI Text Message"; // The message Subject line. cbMsgProperties = sizeof(SPropTagArray) + cMsgProperties * (sizeof(SPropValue) + (wcslen(pszSubject) + 3) * sizeof(WCHAR)); hr = MAPIAllocateBuffer(cbMsgProperties, (LPVOID FAR *)&rgpMsgProperties); memset(rgpMsgProperties, 0, cbMsgProperties); rgpMsgProperties[0].ulPropTag = PR_SUBJECT; rgpMsgProperties[0].Value.lpszW = pszSubject; rgpMsgProperties[1].ulPropTag = PR_MESSAGE_FLAGS; rgpMsgProperties[1].Value.ul = MSGFLAG_FROMME | MSGFLAG_UNSENT; // A combination of flags. rgpMsgProperties[2].ulPropTag = PR_MSG_STATUS; rgpMsgProperties[2].Value.ul = MSGSTATUS_RECTYPE_SMTP; rgpMsgProperties[3].ulPropTag = PR_IMPORTANCE; rgpMsgProperties[3].Value.ul = IMPORTANCE_HIGH; hr = pMsg->SetProps(cMsgProperties, rgpMsgProperties, NULL); hr = MAPIFreeBuffer((void *)rgpMsgProperties); LPSTREAM pStream = NULL; hr = pMsg->OpenProperty(PR_BODY, NULL, 0, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN *)&pStream); LPWSTR pszBody = L"Text in Body of Message."; ULONG cbBody = 0; ULONG cbWritten = 0; cbBody = (wcslen(pszBody) + 1) * sizeof(WCHAR); hr = pStream->Write(pszBody, cbBody, &cbWritten); pStream->Release(); pStream = NULL; hr = pMsg->SubmitMessage(0); pMsg->Release(); pMsg = NULL; } |
Both the Windows Mobile Professional SDK and the Windows Mobile Standard SDK ship with a code sample called Sending E-mail, which you can build and run to gain a better understanding of the fundamental messaging concepts. The default location for the sample:
C:\Program Files\Windows Mobile 6.5.3 DTK\Samples\Common\CPP\Win32\SendMail\SendMail.sln
Compiling the Code
To compile the code sample, you must add references to the CE MAPI type library and the CE MAPI header files, to your project.
- Add preprocessor directives that include the header files in
with the rest of your project files when you build your project.
You do this by typing the following statements at the top of either
your main C++ source file or your header file.
Copy Code #include <cemapi.h> #include <mapidefs.h> #include <mapiutil.h> #include <mapix.h>
- Specify a linker dependency to the CE MAPI type library as a
project property.
- Press
Alt+F7, and the
Project Property Pagesdialog box appears.
- In the dialog box, navigate to the
Inputproperty page for the
Linker(navigate to
Configuration Properties>
Linker>
Input).
- In
Additional Dependencies, type cemapi.lib, and then click
OK.
- Press
Alt+F7, and the
Project Property Pagesdialog box appears.
- Rebuild the Solution (press
Ctrl+Alt+F7).
Robust Programming
A robust program is one that continues normal execution after surviving circumstances that cause lesser programs to crash. Robust programs are designed from the ground-up with error handling in mind. To facilitate this, Win32 COM functions and methods always return success/failure information in the form of a 32-bit HRESULT, which you can use to "trap" conditions that you anticipate will cause problems for your program.
The header file winerror.h contains the error code definitions along with a host of generic error handling macros that you can use in your code. For example, you can use the following two macros to test for success and failure of any COM procedure call.
Copy Code | |
---|---|
#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) // Note that non-negative numbers indicate success. #define FAILED(hr) ((HRESULT)(hr) < 0) |
The following code example is a typical method that demonstrates robust programming.
Copy Code | |
---|---|
BOOL MAessaging::LogOntoMAPI() { HRESULT hr; hr = MAPILogonEx(0, NULL, NULL, 0, (LPMAPISESSION *)&pSession); if(FAILED(hr)) { MessageBox(NULL, _T("Failed to log onto the MAPI Session."), _T("Warning"), MB_OK); return FALSE; } return TRUE; } |