Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

651 lines
14 KiB

// SendMail.cpp: implementation of the CSendMail class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "amisafe.h"
#include "SendMail.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSendMail::CSendMail(CInitMapi &_mapi) : pmsg(NULL), pmapi(_mapi)
{
}
CSendMail::~CSendMail()
{
if (pmsg != NULL)
UlRelease(pmsg);
}
//
// Create an outbound message, put data in it.
//
HRESULT CSendMail::CreateMail(LPSTR szSubject)
{
HRESULT hr;
hr = HrCreateOutMessage(pmapi.pfldOutBox, &pmsg);
if(hr)
return hr;
hr = HrInitMsg(pmsg, pmapi.pvalSentMailEID, szSubject);
if(HR_FAILED(hr)) {
UlRelease(pmsg);
return hr;
}
return hr;
}
HRESULT CSendMail::Transmit()
{
HRESULT hr;
if (pmsg != NULL)
hr = pmsg->SubmitMessage(0);
return hr;
}
//
// Create a message in the outbox
//
HRESULT CSendMail::HrCreateOutMessage(LPMAPIFOLDER pfldOutBox, LPMESSAGE FAR * ppmM)
{
LPMESSAGE lpmResM = NULL;
HRESULT hr;
Assert(pfldOutBox);
hr = pfldOutBox->CreateMessage(NULL, MAPI_DEFERRED_ERRORS, &lpmResM);
if(HR_FAILED(hr))
{
return hr;
}
*ppmM = lpmResM;
return hrSuccess;
}
//
// Put the data from globals in the message
//
HRESULT CSendMail::HrInitMsg(LPMESSAGE pmsg, LPSPropValue pvalSentMailEID, LPSTR szSubject)
{
HRESULT hr;
enum {iSubj, iSentMail, iConvTopic, iConvIdx, iMsgClass, cProps};
// PR_SUBJECT, PR_SENTMAIL_ENTRYID,
// PR_CONVERSATION_TOPIC, PR_COVERSATION_INDEX
SPropValue props[cProps];
ULONG cbConvIdx = 0;
LPBYTE lpbConvIdx = NULL;
//subject and conversation topic
if(szSubject)
{
props[iSubj].ulPropTag = PR_SUBJECT;
props[iSubj].Value.LPSZ = szSubject;
props[iConvTopic].ulPropTag = PR_CONVERSATION_TOPIC;
props[iConvTopic].Value.LPSZ = szSubject;
}
else
{
props[iSubj].ulPropTag = PR_NULL;
props[iConvTopic].ulPropTag = PR_NULL;
}
// conversaton index
//if(!ScAddConversationIndex(0, NULL, &cbConvIdx, &lpbConvIdx))
//{
// props[iConvIdx].ulPropTag = PR_CONVERSATION_INDEX;
// props[iConvIdx].Value.bin.lpb = lpbConvIdx;
// props[iConvIdx].Value.bin.cb = cbConvIdx;
//}
//else
//{
props[iConvIdx].ulPropTag = PR_NULL;
//}
// sent mail entry id (we want to leave a copy in the "Sent Items" folder)
props[iSentMail] = *pvalSentMailEID;
props[iMsgClass].ulPropTag = PR_MESSAGE_CLASS;
props[iMsgClass].Value.lpszA = "IPM.Note";
hr = pmsg->SetProps(cProps, (LPSPropValue)&props, NULL);
if(HR_FAILED(hr))
{
goto err;
}
err:
if (lpbConvIdx != NULL)
MAPIFreeBuffer(lpbConvIdx);
return hr;
}
HRESULT CSendMail::SetRecipients(LPSTR szRecipients)
{
LPADRLIST pal = NULL;
HRESULT hr;
//recipients
hr = HrCreateAddrList(pmapi.pabAddrB, &pal, szRecipients);
if(HR_FAILED(hr))
goto err;
Assert(pal);
hr = pmsg->ModifyRecipients(0, pal);
if(HR_FAILED(hr))
{
goto err;
}
err:
FreePadrlist(pal);
return hr;
}
//
// Create an adrlist with resolved recipients
//
HRESULT CSendMail::HrCreateAddrList(LPADRBOOK pabAddrB, LPADRLIST * ppal, LPSTR szToRecips)
{
HRESULT hr;
LPADRLIST pal = NULL;
int ind;
#define chDELIMITER ';'
int nToRecips = 1;
LPSTR strToken = szToRecips;
while (strToken = strchr(strToken, chDELIMITER))
{
++strToken;
++nToRecips;
}
int cb = CbNewADRLIST(nToRecips);
hr = MAPIAllocateBuffer(cb, (LPVOID FAR *) &pal);
if(hr)
{
goto err;
}
ZeroMemory(pal, cb);
hr = MAPIAllocateBuffer(2 * sizeof(SPropValue),
(LPVOID FAR *)&pal->aEntries[0].rgPropVals);
if(hr)
{
goto err;
}
pal->aEntries[0].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
pal->aEntries[0].rgPropVals[0].Value.LPSZ = szToRecips;
pal->aEntries[0].rgPropVals[1].ulPropTag = PR_RECIPIENT_TYPE;
pal->aEntries[0].rgPropVals[1].Value.l= MAPI_TO;
pal->aEntries[0].cValues = 2;
strToken = szToRecips;
for(ind = 1; ind < nToRecips; ++ind)
{
LPADRENTRY pae = &pal->aEntries[ind];
hr = MAPIAllocateBuffer(2 * sizeof(SPropValue),
(LPVOID FAR *)&pae->rgPropVals);
if(hr)
{
goto err;
}
strToken = strchr(strToken, chDELIMITER);
Assert(strToken);
*strToken++ = '\0';
pae->rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
pae->rgPropVals[0].Value.LPSZ = strToken;
pae->rgPropVals[1].ulPropTag = PR_RECIPIENT_TYPE;
pae->rgPropVals[1].Value.l = MAPI_TO;
pae->cValues = 2;
}
pal->cEntries = nToRecips;
hr = pabAddrB->ResolveName(0, 0, NULL, pal);
if(HR_FAILED(hr))
{
goto err;
}
*ppal = pal;
return hrSuccess;
err:
FreePadrlist(pal);
return hr;
}
//////////////////////////////////////////////////////////////////////
// CInitMapi Class
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CInitMapi::CInitMapi() : fMAPIInited(FALSE), pabAddrB(NULL),
pfldOutBox(NULL), pmdb(NULL), pses(NULL), pvalSentMailEID(NULL)
{
}
CInitMapi::~CInitMapi()
{
DeInitMapi();
}
//
// Init MAPI. Open address book, default message store, outbox
//
HRESULT CInitMapi::InitMapi(void)
{
HRESULT hr;
hr = MAPIInitialize(NULL);
if(hr)
{
return hr;
}
fMAPIInited = TRUE;
hr = MAPILogonEx( NULL, NULL /* szProfile */ , NULL /* szPassword */,
MAPI_EXTENDED | MAPI_NEW_SESSION | MAPI_USE_DEFAULT,
&pses);
if(hr)
{
goto err;
}
hr = HrOpenDefaultStore(pses, &pmdb);
if(HR_FAILED(hr))
goto err;
hr = HrOpenAddressBook(pses, &pabAddrB);
if(HR_FAILED(hr))
goto err;
hr = HrOpenOutFolder(pses, pmdb, &pfldOutBox);
if(HR_FAILED(hr))
goto err;
/* retrieve the EntryID of the sentmail folder and change the property tag
so that it is ready to use on a message*/
hr = HrGetOneProp((LPMAPIPROP)pmdb, PR_IPM_SENTMAIL_ENTRYID, &pvalSentMailEID);
if(hr)
{
goto err;
}
pvalSentMailEID->ulPropTag = PR_SENTMAIL_ENTRYID;
return hrSuccess;
err:
DeInitMapi();
return hr;
}
//
// Release MAPI interfaces and logoff
//
void CInitMapi::DeInitMapi(void)
{
if (pfldOutBox != NULL)
{
UlRelease(pfldOutBox);
pfldOutBox = NULL;
}
if(pmdb != NULL)
{
//get our message out of the outbox
ULONG ulFlags = LOGOFF_PURGE;
HRESULT hr;
hr = pmdb->StoreLogoff(&ulFlags);
UlRelease(pmdb);
pmdb = NULL;
}
if (pabAddrB != NULL) {
UlRelease(pabAddrB);
pabAddrB = NULL;
}
if (pvalSentMailEID != NULL) {
MAPIFreeBuffer(pvalSentMailEID);
pvalSentMailEID = NULL;
}
if(pses != NULL)
{
pses->Logoff(0, 0, 0);
UlRelease(pses);
pses = NULL;
}
if(fMAPIInited)
{
MAPIUninitialize();
fMAPIInited = FALSE;
}
}
//
// Open the default message store. (The one that has PR_DEFAULT_STORE set to
// TRUE in the message store table.
//
HRESULT CInitMapi::HrOpenDefaultStore(LPMAPISESSION pses, LPMDB * ppmdb)
{
HRESULT hr;
LPMDB lpmdb = NULL;
LPMAPITABLE ptable = NULL;
LPSRowSet prows = NULL;
LPSPropValue pvalProp = NULL;
static SizedSPropTagArray(2, columns) =
{ 2, { PR_DEFAULT_STORE, PR_ENTRYID} };
SPropValue valDefStore;
SRestriction restDefStore;
valDefStore.ulPropTag = PR_DEFAULT_STORE;
valDefStore.dwAlignPad = 0;
valDefStore.Value.b = TRUE;
restDefStore.rt = RES_PROPERTY;
restDefStore.res.resProperty.relop = RELOP_EQ;
restDefStore.res.resProperty.ulPropTag = PR_DEFAULT_STORE;
restDefStore.res.resProperty.lpProp = &valDefStore;
Assert(pses);
hr = pses->GetMsgStoresTable(0, &ptable);
if (HR_FAILED(hr))
{
goto ret;
}
hr = HrQueryAllRows(ptable, (LPSPropTagArray) &columns, &restDefStore, NULL, 0, &prows);
if (HR_FAILED(hr))
{
goto ret;
}
if (prows == NULL || prows->cRows == 0
|| prows->aRow[0].lpProps[1].ulPropTag != PR_ENTRYID)
{
::MessageBox(NULL, "No default store", NULL, MB_OK);
goto ret;
}
Assert(prows->cRows == 1);
hr = pses->OpenMsgStore(0,
prows->aRow[0].lpProps[1].Value.bin.cb,
(LPENTRYID)prows->aRow[0].lpProps[1].Value.bin.lpb,
NULL, MDB_WRITE | MAPI_DEFERRED_ERRORS, &lpmdb);
if (HR_FAILED(hr))
{
//if (GetScode(hr) != MAPI_E_USER_CANCEL)
// TraceFnResult(OpenMsgStore, hr);
goto ret;
}
#if 0
if(hr) /*if we have a warning, display it and succeed */
{
LPMAPIERROR perr = NULL;
pses->lpVtbl->GetLastError(pses, hr, 0, &perr);
MakeMessageBox(hWnd, GetScode(hr), IDS_OPENSTOREWARN, perr, MBS_ERROR);
MAPIFreeBuffer(perr);
}
#endif
Assert(lpmdb != NULL);
*ppmdb = lpmdb;
ret:
FreeProws(prows);
UlRelease(ptable);
return hr;
}
//
// Open MAPI address book
//
HRESULT CInitMapi::HrOpenAddressBook(LPMAPISESSION pses, LPADRBOOK * ppAddrBook)
{
HRESULT hr;
LPADRBOOK pabAddrBook = NULL;
Assert(pses);
hr = pses->OpenAddressBook(0, NULL, 0, &pabAddrBook);
if(HR_FAILED(hr))
{
return hr;
}
#if 0
if(hr) /*if we have a warning*/
{
LPMAPIERROR perr = NULL;
pses->lpVtbl->GetLastError(pses, hr, 0, &perr);
MakeMessageBox(hwnd, GetScode(hr), IDS_OPENABWARN, perr, MBS_ERROR);
MAPIFreeBuffer(perr);
}
#endif
*ppAddrBook = pabAddrBook;
return hrSuccess;
}
//
// Open the outbox of the default store.
// Assumes the default message store has been opened.
//
HRESULT CInitMapi::HrOpenOutFolder(LPMAPISESSION pses, LPMDB pmdb, LPMAPIFOLDER FAR * lppF)
{
LPMAPIFOLDER lpfOutF = NULL;
HRESULT hr;
LPSPropValue lpspvFEID = NULL;
ULONG ulObjType = 0;
Assert(pmdb);
*lppF = NULL;
hr = HrGetOneProp((LPMAPIPROP) pmdb, PR_IPM_OUTBOX_ENTRYID, &lpspvFEID);
if(hr)
{
goto err;
}
Assert(lpspvFEID->ulPropTag == PR_IPM_OUTBOX_ENTRYID);
hr = pmdb->OpenEntry(lpspvFEID->Value.bin.cb,
(LPENTRYID)lpspvFEID->Value.bin.lpb, NULL,
MAPI_MODIFY | MAPI_DEFERRED_ERRORS,
&ulObjType, (LPUNKNOWN FAR *) &lpfOutF);
if(HR_FAILED(hr))
{
goto err;
}
*lppF = lpfOutF;
err:
MAPIFreeBuffer(lpspvFEID);
return hr;
}
//////////////////////////////////////////////////////////////////////
// CAddressEnum Class
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CAddressEnum::CAddressEnum(CInitMapi &_mapi): pmapi(_mapi)
{
}
CAddressEnum::~CAddressEnum()
{
}
HRESULT CAddressEnum::HrLookupSingleAddr(LPADRBOOK pabAddrB,
LPSTR szInputName,
LPSTR szResultBuffer, DWORD dwBufferSize)
{
HRESULT hr;
LPADRLIST pal = NULL;
int cb = CbNewADRLIST(1);
hr = MAPIAllocateBuffer(cb, (LPVOID FAR *) &pal);
if(hr) {
goto err;
}
ZeroMemory(pal, cb);
hr = MAPIAllocateBuffer(2 * sizeof(SPropValue),
(LPVOID FAR *)&pal->aEntries[0].rgPropVals);
if(hr) {
goto err;
}
pal->aEntries[0].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
pal->aEntries[0].rgPropVals[0].Value.lpszA = szInputName;
pal->aEntries[0].rgPropVals[1].ulPropTag = PR_RECIPIENT_TYPE;
pal->aEntries[0].rgPropVals[1].Value.l= MAPI_TO;
pal->aEntries[0].cValues = 2;
pal->cEntries = 1;
hr = pabAddrB->ResolveName(0, 0, NULL, pal);
if(HR_FAILED(hr)) {
goto err;
}
for (int ind = 0; ind < (int) pal->cEntries; ind++) {
for (int prop = 0; prop < (int) pal->aEntries[ind].cValues; prop++) {
if (pal->aEntries[ind].rgPropVals[prop].ulPropTag == PR_DISPLAY_NAME ||
pal->aEntries[ind].rgPropVals[prop].ulPropTag == PR_EMAIL_ADDRESS) {
strncpy(szResultBuffer,
pal->aEntries[ind].rgPropVals[prop].Value.lpszA,
dwBufferSize);
szResultBuffer[dwBufferSize - 1] = '\0';
hr = S_OK;
goto err;
}
}
}
hr = MAPI_E_NOT_FOUND;
err:
FreePadrlist(pal);
return hr;
}
HRESULT CAddressEnum::LookupAddress(LPSTR szInputName, LPSTR szResultBuffer, DWORD dwBufferSize)
{
return HrLookupSingleAddr(pmapi.pabAddrB, szInputName, szResultBuffer, dwBufferSize);
}
#if 0
HRESULT hr;
LPABCONT pabRootCont; // IABContainer
LPMAPITABLE pMapiTable;
// LPADRBOOK IAddrBook
// Open the address book's root container
hr = pmapi.pabAddrB->OpenEntry(0, NULL, IABContainer, MAPI_BEST_ACCESS,
NULL, (LPUNKNOWN FAR *) &pabRootCont);
if (HR_FAILED(hr)) {
return hr;
}
hr = pabRootCont->GetContentsTable(0, &pMapiTable);
if (HR_FAILED(hr)) {
UlRelease(pabRootCont);
return hr;
}
hr = HrQueryAllRows(pMapiTable,
LPSPropTagArray ptaga,
LPSRestriction pres,
NULL, // sort order
10, // maximum records to return
LPSRowSet FAR * pprows
);
GetContentsTable
IMAPITable::SortTable,
IMAPITable::QueryRows
#endif