// 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