Last active
August 25, 2016 06:32
-
-
Save bosim/aaaaf0f579615f58aad7f68257b27503 to your computer and use it in GitHub Desktop.
mapi-synchronization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Example of mapi synchronization | |
// State will be saved to test.dat (you need to create it in advance), | |
// first run: full sync (ImportMessageChange) will be called for all messages | |
// next run: state is read and only differences (i.e. message change, deletion, flag change) | |
// will be fetched and the appropriate methods in the class will be called. | |
#include <kopano/stringutil.h> | |
#include "platform.h" | |
#include <iostream> | |
#include <mapi.h> | |
#include <mapiutil.h> | |
#include <kopano/Util.h> | |
#include <kopano/ECLogger.h> | |
#include "CommonUtil.h" | |
#include "inetmapi/inetmapi.h" | |
#include <edkguid.h> | |
#include <unistd.h> | |
using namespace std; | |
IAddrBook *lpAddrBook; | |
ECLogger* lpLogger; | |
sending_options sopt; | |
delivery_options dopt; | |
class ECImportContentsChangesProxy : public IExchangeImportContentsChanges { | |
public: | |
ECImportContentsChangesProxy() { | |
this->m_cRef = 1; | |
} | |
ULONG AddRef() { | |
return ++m_cRef; | |
}; | |
ULONG Release() { | |
if (--m_cRef == 0) { | |
delete this; | |
return 0; | |
} | |
return m_cRef; | |
} | |
HRESULT QueryInterface(REFIID iid, void **lpvoid) { | |
if(iid == IID_IExchangeImportContentsChanges) { | |
AddRef(); | |
*lpvoid = this; | |
return hrSuccess; | |
} | |
return MAPI_E_INTERFACE_NOT_SUPPORTED; | |
} | |
HRESULT GetLastError(HRESULT hResult, ULONG ulFlags, LPMAPIERROR *lppMAPIError) { | |
return hrSuccess; | |
} | |
HRESULT Config(LPSTREAM lpStream, ULONG ulFlags) { | |
return hrSuccess; | |
} | |
HRESULT UpdateState(LPSTREAM lpStream) { | |
return hrSuccess; | |
} | |
HRESULT ImportMessageChange(ULONG cValue, LPSPropValue lpPropArray, ULONG ulFlags, LPMESSAGE * lppMessage) { | |
LPSPropValue lpPropValE = PpropFindProp(lpPropArray, cValue, PR_ENTRYID); | |
LPSPropValue lpPropValS = PpropFindProp(lpPropArray, cValue, PR_SOURCE_KEY); | |
char* strEntryID = NULL; | |
Util::bin2hex(lpPropValE->Value.bin.cb, lpPropValE->Value.bin.lpb, | |
&strEntryID, NULL); | |
std::cout << "Msg recieved " << strEntryID << std::endl; | |
Util::bin2hex(lpPropValS->Value.bin.cb, lpPropValS->Value.bin.lpb, | |
&strEntryID, NULL); | |
std::cout << "Source id " << strEntryID << std::endl; | |
return hrSuccess; | |
} | |
HRESULT ImportMessageDeletion(ULONG ulFlags, LPENTRYLIST lpSourceEntryList) { | |
char* strEntryID; | |
std::cout << "Msg delete " << std::endl; | |
std::cout << lpSourceEntryList->cValues << std::endl; | |
for(int i=0; i < lpSourceEntryList->cValues; i++) { | |
Util::bin2hex(lpSourceEntryList->lpbin[i].cb, lpSourceEntryList->lpbin[i].lpb, | |
&strEntryID, NULL); | |
std::cout << "D: " << strEntryID << std::endl; | |
} | |
return hrSuccess; | |
} | |
HRESULT ImportMessageMove(ULONG cbSourceKeySrcFolder, BYTE FAR * pbSourceKeySrcFolder, ULONG cbSourceKeySrcMessage, BYTE FAR * pbSourceKeySrcMessage, ULONG cbPCLMessage, BYTE FAR * pbPCLMessage, ULONG cbSourceKeyDestMessage, BYTE FAR * pbSourceKeyDestMessage, ULONG cbChangeNumDestMessage, BYTE FAR * pbChangeNumDestMessage) { | |
return MAPI_E_NO_SUPPORT; | |
} | |
HRESULT ImportPerUserReadStateChange(ULONG cElements, LPREADSTATE lpReadState) { | |
std::cout << "Msg read state change" << std::endl; | |
char* strEntryID; | |
for(int i=0; i < cElements; i++) { | |
Util::bin2hex(lpReadState[i].cbSourceKey, lpReadState[i].pbSourceKey, | |
&strEntryID, NULL); | |
std::cout << "C: " << strEntryID << " flags " << lpReadState[i].ulFlags << std::endl; | |
} | |
return hrSuccess; | |
} | |
private: | |
ULONG m_cRef; | |
}; | |
int main(int argc, char *argv[]) | |
{ | |
HRESULT hr = S_OK; | |
IMAPISession *lpSession = NULL; | |
ULONG cbEntryID = 0; | |
LPMDB lpStore = NULL; | |
LPENTRYID lpEntryID = NULL; | |
ULONG ulType = 0; | |
LPSTREAM lpStream = NULL; | |
IMAPIFolder *lpInbox = NULL; | |
LPMESSAGE lpMessage = 0; | |
ULONG ulRows = 0; | |
LPSSortOrderSet lpSortCriteria = NULL; | |
LPSPropValue lpPropVal = NULL; | |
SPropValue propName; | |
SBinary sEntryID; | |
std::string input, stdStr; | |
ULONG ulObjType; | |
IMAPIFolder *lpFolder = NULL; | |
IExchangeExportChanges *lpIEEC = NULL; | |
ULONG ulSteps = 0; | |
ULONG ulProgress = 0; | |
LARGE_INTEGER lint = {{ 0, 0 }}; | |
ULONG tmp[2] = { 0, 0 }; | |
ULONG ulSize = 0; | |
imopt_default_sending_options(&sopt); | |
sopt.no_recipients_workaround = true; // do not stop processing mail on empty recipient table | |
sopt.add_received_date = true; | |
imopt_default_delivery_options(&dopt); | |
ECImportContentsChangesProxy* proxy = new ECImportContentsChangesProxy(); | |
lpLogger = new ECLogger_File(EC_LOGLEVEL_ALWAYS, true, "test.log", false); | |
ec_log_set(lpLogger); | |
// Initialize mapi system | |
hr = MAPIInitialize(NULL); | |
wchar_t user[20]; | |
wchar_t pass[20]; | |
mbstowcs(user, "XXX", 20); | |
mbstowcs(pass, "XXX", 20); | |
hr = HrOpenECSession(lpLogger, &lpSession, "test", "0", user, pass, "http://localhost:236"); | |
if (hr != hrSuccess) { | |
cout << "Cannot open session for user " <<argv[1]<< " with pass " <<argv[2]<< " on server " <<argv[3]<< endl; | |
} | |
// Get the default Store of the profile | |
hr = HrOpenDefaultStore(lpSession, &lpStore); | |
if (hr != hrSuccess) { | |
cout << "Unable to open default store" << endl; | |
} | |
// Receive the Inbox | |
hr = lpStore->GetReceiveFolder("IPM", 0, &cbEntryID, &lpEntryID, NULL); | |
if (hr != hrSuccess) { | |
cout << "Unable to get inbox folder ID" << endl; | |
} | |
// Open the inbox | |
hr = lpStore->OpenEntry(cbEntryID, lpEntryID, &IID_IMAPIFolder, MAPI_MODIFY, &ulType, (LPUNKNOWN *)&lpInbox); | |
if (hr != hrSuccess) { | |
cout << "Unable to open inbox" << endl; | |
} | |
hr = CreateStreamOnHGlobal(GlobalAlloc(GPTR, sizeof(tmp)), true, &lpStream); | |
lpIEEC = NULL; | |
hr = lpInbox->OpenProperty(PR_CONTENTS_SYNCHRONIZER, &IID_IExchangeExportChanges, 0, 0, (LPUNKNOWN *)&lpIEEC); | |
if (hr != hrSuccess) { | |
cout << "Unable to open inbox" << endl; | |
} | |
char buf[4096]; | |
FILE* fh = fopen("test.dat", "r"); | |
int bytes = fread(buf, 1, 4096, fh); | |
lpStream->Write(buf, bytes, NULL); | |
lpStream->Commit(0); | |
hr = lpIEEC->Config(lpStream, SYNC_NORMAL | SYNC_READ_STATE | SYNC_NO_CONFLICTS, proxy, NULL, NULL, NULL, 0); | |
if (hr != hrSuccess) { | |
cout << "Config failed"; | |
} | |
do { | |
hr = lpIEEC->Synchronize(&ulSteps, &ulProgress); | |
std::cout << ulSteps << " " << ulProgress << std::endl; | |
} while(hr == SYNC_W_PROGRESS); | |
ULONG ulRead; | |
std::cout << lpStream << std::endl; | |
fh = fopen("test.dat", "w"); | |
lpStream->Seek(lint, SEEK_SET, NULL); | |
hr = lpStream->Read(buf, 4096, &ulRead); | |
fwrite(buf, ulRead, 1, fh); | |
fclose(fh); | |
MAPIUninitialize(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment