mirror of https://github.com/tongzx/nt5src
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
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
|