HRESULT MAPIAppointment::UpdateAttendeeFromEntryId(Attendee &pAttendee,
    SBinary &eid)
{
    Zimbra::Util::ScopedInterface<IMailUser> pUser;
    ULONG ulObjType = 0;
	if(!m_pAddrBook)
		return E_FAIL;
    HRESULT hr = m_pAddrBook->OpenEntry(eid.cb, (LPENTRYID)eid.lpb, NULL, MAPI_BEST_ACCESS,
        &ulObjType, (LPUNKNOWN *)pUser.getptr());

    if (FAILED(hr) || (ulObjType != MAPI_MAILUSER))
        return E_FAIL;
    SizedSPropTagArray(3, tags) = {
        3, { PR_ADDRTYPE_W, PR_DISPLAY_NAME_W, PR_EMAIL_ADDRESS_W }
    };

    ULONG cVals = 0;
    Zimbra::Util::ScopedBuffer<SPropValue> pVals;

    hr = pUser->GetProps((LPSPropTagArray) & tags, MAPI_UNICODE, &cVals, pVals.getptr());
    if (FAILED(hr))
        return hr;
    // no smtp address, bail
    if ((pVals->ulPropTag != PR_ADDRTYPE_W) || (wcsicmp(pVals->Value.lpszW, L"SMTP") != 0))
        return E_FAIL;
    if ((pVals[1].ulPropTag == PR_DISPLAY_NAME_W) && ((pAttendee.nam == L"")))
        pAttendee.nam = pVals[1].Value.lpszW;
    if ((pVals[2].ulPropTag == PR_EMAIL_ADDRESS_W) && (pAttendee.addr == L""))
        pAttendee.addr=pVals[2].Value.lpszW;

	return S_OK;
}
Пример #2
0
HRESULT ExchangeAdmin::DeleteProfile(wstring strProfile)
{
    HRESULT hr = S_OK;
    Zimbra::Util::ScopedBuffer<char> strProfName;

    WtoA((LPWSTR)strProfile.c_str(), strProfName.getref());
    // delete profile
    if (FAILED(hr = m_pProfAdmin->DeleteProfile((LPTSTR)strProfName.get(), 0)) && (hr !=
        MAPI_E_NOT_FOUND))
        throw ExchangeAdminException(hr, L"DeleteProfile(): DeleteProfile Failed.",
		ERR_DELETE_PROFILE, __LINE__, __FILE__);
    return hr;
}
Пример #3
0
HRESULT MAPIFolder::ContainerClass(wstring &wstrContainerClass)
{
    if (!m_folder)
        return E_FAIL;

    HRESULT hr = S_OK;
    Zimbra::Util::ScopedBuffer<SPropValue> pPropValues;

    wstrContainerClass = L"";
    if (SUCCEEDED(hr = HrGetOneProp(m_folder, PR_CONTAINER_CLASS, pPropValues.getptr())))
        wstrContainerClass = pPropValues->Value.LPSZ;
    return hr;
}
Пример #4
0
bool MAPIFolder::HiddenFolder()
{
    if (!m_folder)
        return false;

    HRESULT hr = S_OK;
    bool bRet = false;
    Zimbra::Util::ScopedBuffer<SPropValue> pPropValues;

    if (SUCCEEDED(hr = HrGetOneProp(m_folder, PR_ATTR_HIDDEN, pPropValues.getptr())))
        bRet = (pPropValues->Value.b != 0);
    return bRet;
}
Пример #5
0
HRESULT MAPITask::InitNamedPropsForTask()
{
    // init named props
    nameIds[0] = 0x8126;
    nameIds[1] = 0x8116;
    nameIds[2] = 0x8101;
    nameIds[3] = 0x8102;
    nameIds[4] = 0x8104;
    nameIds[5] = 0x8105;
    nameIds[6] = 0x8111;
    nameIds[7] = 0x8110;

    nameIdsC[0] = 0x8539;
    nameIdsC[1] = 0x8534;
    nameIdsC[2] = 0x8535;
    nameIdsC[3] = 0x8503;
    nameIdsC[4] = 0x8560;
    nameIdsC[5] = 0x8506;

    HRESULT hr = S_OK;
    Zimbra::Util::ScopedBuffer<SPropValue> pPropValMsgClass;

    if (FAILED(hr = HrGetOneProp(m_pMessage, PR_MESSAGE_CLASS, pPropValMsgClass.getptr())))
        throw MAPITaskException(hr, L"InitNamedPropsForTask(): HrGetOneProp Failed.",
                                ERR_MAPI_TASK, __LINE__, __FILE__);

    // initialize the MAPINAMEID structure GetIDsFromNames requires
    LPMAPINAMEID ppNames[N_NUMTASKPROPS] = { 0 };
    for (int i = 0; i < N_NUMTASKPROPS; i++)
    {
        MAPIAllocateBuffer(sizeof (MAPINAMEID), (LPVOID *)&(ppNames[i]));
        ppNames[i]->ulKind = MNID_ID;
        ppNames[i]->lpguid = (LPGUID)(&PS_OUTLOOK_TASK);
        ppNames[i]->Kind.lID = nameIds[i];
    }

    LPMAPINAMEID ppNamesC[N_NUMCOMMONTPROPS] = { 0 };
    for (int i = 0; i < N_NUMCOMMONTPROPS; i++)
    {
        MAPIAllocateBuffer(sizeof (MAPINAMEID), (LPVOID *)&(ppNamesC[i]));
        ppNamesC[i]->ulKind = MNID_ID;
        ppNamesC[i]->lpguid = (LPGUID)(&PS_OUTLOOK_COMMON);
        ppNamesC[i]->Kind.lID = nameIdsC[i];
    }

    // get the real prop tag ID's
    LPSPropTagArray pTaskTags  = NULL;
    LPSPropTagArray pTaskTagsC = NULL;

    if (FAILED(hr = m_pMessage->GetIDsFromNames(N_NUMTASKPROPS, ppNames, MAPI_CREATE,
                    &pTaskTags)))
        throw MAPITaskException(hr, L"Init(): GetIDsFromNames on pTaskTags Failed.", ERR_MAPI_TASK,
                                __LINE__, __FILE__);

    if (FAILED(hr = m_pMessage->GetIDsFromNames(N_NUMCOMMONTPROPS, ppNamesC, MAPI_CREATE,
                    &pTaskTagsC)))
        throw MAPITaskException(hr, L"Init(): GetIDsFromNames on pAppointmentTagsC Failed.", ERR_MAPI_TASK,
                                __LINE__, __FILE__);

    // give the prop tag ID's a type
    pr_isrecurringt = SetPropType(pTaskTags->aulPropTag[N_ISRECURT], PT_BOOLEAN);
    pr_recurstreamt = SetPropType(pTaskTags->aulPropTag[N_RECURSTREAMT], PT_BINARY);
    pr_status = SetPropType(pTaskTags->aulPropTag[N_STATUS], PT_LONG);
    pr_percentcomplete = SetPropType(pTaskTags->aulPropTag[N_PERCENTCOMPLETE], PT_DOUBLE);
    pr_taskstart = SetPropType(pTaskTags->aulPropTag[N_TASKSTART], PT_SYSTIME);
    pr_taskdue = SetPropType(pTaskTags->aulPropTag[N_TASKDUE], PT_SYSTIME);
    pr_totalwork = SetPropType(pTaskTags->aulPropTag[N_TOTALWORK], PT_LONG);
    pr_actualwork = SetPropType(pTaskTags->aulPropTag[N_ACTUALWORK], PT_LONG);
    pr_companies = SetPropType(pTaskTagsC->aulPropTag[N_COMPANIES], PT_MV_TSTRING);
    pr_mileage = SetPropType(pTaskTagsC->aulPropTag[N_MILEAGE], PT_TSTRING);
    pr_billinginfo = SetPropType(pTaskTagsC->aulPropTag[N_BILLING], PT_TSTRING);
    pr_taskreminderset = SetPropType(pTaskTagsC->aulPropTag[N_TASKREMINDERSET], PT_BOOLEAN);
    pr_taskflagdueby = SetPropType(pTaskTagsC->aulPropTag[N_TASKFLAGDUEBY], PT_SYSTIME);
    pr_private = SetPropType(pTaskTagsC->aulPropTag[N_TPRIVATE], PT_BOOLEAN);

    // free the memory we allocated on the head
    for (int i = 0; i < N_NUMTASKPROPS; i++)
    {
        MAPIFreeBuffer(ppNames[i]);
    }
    for (int i = 0; i < N_NUMCOMMONTPROPS; i++)
    {
        MAPIFreeBuffer(ppNamesC[i]);
    }
    MAPIFreeBuffer(pTaskTags);
    MAPIFreeBuffer(pTaskTagsC);

    //MAPITask::m_bNamedPropsInitialized = true;

    return S_OK;
}
Пример #6
0
HRESULT ExchangeAdmin::CreateProfile(wstring strProfileName, wstring strMailboxName, wstring
    strPassword)
{
    HRESULT hr = S_OK;
    Zimbra::Util::ScopedBuffer<char> strServer;
    Zimbra::Util::ScopedBuffer<char> strMBName;
    Zimbra::Util::ScopedBuffer<char> strProfName;
    Zimbra::Util::ScopedBuffer<char> strProfPwd;
    Zimbra::Util::ScopedInterface<IMsgServiceAdmin> pSvcAdmin;
    Zimbra::Util::ScopedInterface<IMAPITable> pMsgSvcTable;
    Zimbra::Util::ScopedRowSet pSvcRows;
    SPropValue rgval[2] = { 0 };
    SPropValue sProps = { 0 };
    SRestriction sres;
    WCHAR errDescrption[256] = {};

    // Columns to get from HrQueryAllRows.
    enum { iSvcName, iSvcUID, cptaSvc };

    SizedSPropTagArray(cptaSvc, sptCols) = { cptaSvc, PR_SERVICE_NAME, PR_SERVICE_UID };
    WtoA((LPWSTR)strProfileName.c_str(), strProfName.getref());
    WtoA((LPWSTR)strPassword.c_str(), strProfPwd.getref());
    // create new profile
    if (FAILED(hr = m_pProfAdmin->CreateProfile((LPTSTR)strProfName.get(),
            (LPTSTR)strProfPwd.get(), NULL, 0)))
    {
        throw ExchangeAdminException(hr, L"CreateProfile(): CreateProfile Failed.", 
			ERR_CREATE_EXCHPROFILE, __LINE__, __FILE__);
    }
    // Get an IMsgServiceAdmin interface off of the IProfAdmin interface.
    if (FAILED(hr = m_pProfAdmin->AdminServices((LPTSTR)strProfName.get(),
            (LPTSTR)strProfPwd.get(), NULL, 0, pSvcAdmin.getptr())))
    {
        wcscpy(errDescrption, L"CreateProfile(): AdminServices Failed.");
        goto CRT_PROFILE_EXIT;
    }
    // Create the new message service for Exchange.
    if (FAILED(hr = pSvcAdmin->CreateMsgService((LPTSTR)"MSEMS", (LPTSTR)"MSEMS", NULL, NULL)))
    {
        wcscpy(errDescrption, L"CreateProfile(): CreateMsgService Failed.");
        goto CRT_PROFILE_EXIT;
    }
    // Need to obtain the entry id for the new service. This can be done by getting the message service table
    // and getting the entry that corresponds to the new service.
    if (FAILED(hr = pSvcAdmin->GetMsgServiceTable(0, pMsgSvcTable.getptr())))
    {
        wcscpy(errDescrption, L"CreateProfile(): GetMsgServiceTable Failed.");
        goto CRT_PROFILE_EXIT;
    }
    sres.rt = RES_CONTENT;
    sres.res.resContent.ulFuzzyLevel = FL_FULLSTRING;
    sres.res.resContent.ulPropTag = PR_SERVICE_NAME;
    sres.res.resContent.lpProp = &sProps;

    sProps.ulPropTag = PR_SERVICE_NAME;
    sProps.Value.lpszA = "MSEMS";
    // Query the table to obtain the entry for the newly created message service.
    if (FAILED(hr = HrQueryAllRows(pMsgSvcTable.get(), (LPSPropTagArray) & sptCols, NULL, NULL,
            0, pSvcRows.getptr())))
    {
        wcscpy(errDescrption, L"CreateProfile(): HrQueryAllRows Failed.");
        goto CRT_PROFILE_EXIT;
    }
    // Set up a SPropValue array for the properties that you have to configure.
    if (pSvcRows->cRows > 0)
    {
        // First, the exchange server name.
        ZeroMemory(&rgval[0], sizeof (SPropValue));
        rgval[0].ulPropTag = PR_PROFILE_UNRESOLVED_SERVER;
        WtoA((LPWSTR)m_strServer.c_str(), strServer.getref());
        rgval[0].Value.lpszA = (LPSTR)strServer.get();

        // Next, the user's AD name.
        ZeroMemory(&rgval[1], sizeof (SPropValue));
        rgval[1].ulPropTag = PR_PROFILE_UNRESOLVED_NAME;
        WtoA((LPWSTR)strMailboxName.c_str(), strMBName.getref());
        rgval[1].Value.lpszA = (LPSTR)strMBName.get();

        // Configure the message service by using the previous properties.
        // int trials = 10;
        int trials = 2;
        int itrTrials = 0;

        hr = 0x81002746;                        // WSAECONNRESET
        while ((hr == 0x81002746) && (itrTrials < trials))
        {
            hr = pSvcAdmin->ConfigureMsgService(
                (LPMAPIUID)pSvcRows->aRow->lpProps[iSvcUID].Value.bin.lpb, NULL, 0, 2, rgval);
            //if (hr == 0x81002746)
                // Sleep(30000);
                //Sleep(10000);
            itrTrials++;
        }
        if (FAILED(hr))
        {
            /* =
             * pSvcAdmin->ConfigureMsgService((LPMAPIUID)pSvcRows->aRow->lpProps[iSvcUID].
             *   Value.bin.lpb,NULL, 0, 2, rgval)))*/
            wcscpy(errDescrption, L"CreateProfile(): ConfigureMsgService Failed.");
            goto CRT_PROFILE_EXIT;
        }
    }
CRT_PROFILE_EXIT: 
	if (hr != S_OK)
    {
        DeleteProfile(strProfileName);
        throw ExchangeAdminException(hr, errDescrption, ERR_CREATE_EXCHPROFILE, __LINE__, __FILE__);
    }
	else
	{
		//Create supporting OL profile entries else crash may happen!
		if(!Zimbra::MAPI::Util::SetOLProfileRegistryEntries(strProfileName.c_str()))
		{
			throw ExchangeAdminException(hr, L"ExchangeAdmin::CreateProfile()::SetOLProfileRegistryEntries Failed.",
				ERR_CREATE_EXCHPROFILE, __LINE__, __FILE__);
		}
/*		Zimbra::Util::ScopedBuffer<char> strProfName;
		WtoA((LPWSTR)strProfileName.c_str(), strProfName.getref());
		hr=m_pProfAdmin->SetDefaultProfile((LPTSTR)strProfName.get(),NULL);
*/
	}
    return hr;
}
Пример #7
0
HRESULT MAPIRfc2445::ExtractAttachments()
{
    // may need to break this up so we can call for exceptions, cancel exceptions

    LPCWSTR errMsg;
    Zimbra::Util::ScopedInterface<IStream> pIStream;
    UINT mimeLen = 0;
    HRESULT hr = ConvertIt( m_pMessage, pIStream.getptr(), mimeLen );
    if (FAILED(hr))
    {
        errMsg = FormatExceptionInfo(hr, L"Mime conversion of message with attachments failed", __FILE__, __LINE__);
        dlogw(errMsg);
        return hr;
    }

    mimepp::Message mimeMsg;
    Zimbra::Util::ScopedBuffer<CHAR> pszMimeMsg;

    // go to the beginning of the stream
    LARGE_INTEGER li = { 0 };

    hr = pIStream->Seek(li, STREAM_SEEK_SET, NULL);
    if (FAILED(hr))
    {
        errMsg = FormatExceptionInfo(hr, L"Stream seek failed", __FILE__, __LINE__);
        dlogw(errMsg);
        return hr;
    }

    // +1 for NULL terminator
    Zimbra::Mapi::Memory::AllocateBuffer(mimeLen + 1, (LPVOID *)pszMimeMsg.getptr());
    if (!pszMimeMsg.get())
    {
        errMsg = FormatExceptionInfo(S_OK, L"Mime msg Memory alloc failed", __FILE__, __LINE__);
        dlogw(errMsg);
        return hr;
    }

    ULONG ulNumRead = 0;

    hr = pIStream->Read((LPVOID)(pszMimeMsg.get()), mimeLen, &ulNumRead);
    if (FAILED(hr))
    {
        errMsg = FormatExceptionInfo(hr, L"Mime msg read failed", __FILE__, __LINE__);
        dlogw(errMsg);
        return hr;
    }
    if (ulNumRead != mimeLen)
    {
        errMsg = FormatExceptionInfo(hr, L"Mime msg read error", __FILE__, __LINE__);
        dlogw(errMsg);
        return hr;
    }

    // terminating string
    pszMimeMsg.get()[mimeLen] = '\0';

    mimeMsg.setString(pszMimeMsg.get());
    mimeMsg.parse();

    // let's see if this message is a multipart alternative before we continue
    mimepp::Headers &theHeaders = mimeMsg.headers();

    LPSTR pszContentType;
    GetContentType(theHeaders, &pszContentType);

    if(strncmp(pszContentType, "multipart/mixed", strlen("multipart/mixed")) != 0) 
    {
        // not what we are looking for
        delete[] pszContentType;
        return S_OK;
    }

    const mimepp::Body& theBody = mimeMsg.body();
    int numParts = theBody.numBodyParts();

    // FBS bug 73682 -- 5/23/12
    int numHiddenAttachments = GetNumHiddenAttachments();
    int totalAttachments = numParts - 1;
    if (totalAttachments == numHiddenAttachments)
    {
        return S_OK;
    }

    // let's look for a multipart mixed and grab the attachments
    int ctr = numHiddenAttachments;
    for(int i = 0; i < numParts; i++) 
    {
        // now look for attachments
        const mimepp::BodyPart& thePart = theBody.bodyPartAt(i);
        mimepp::DispositionType& disposition = thePart.headers().contentDisposition();
        if(disposition.asEnum() == mimepp::DispositionType::ATTACHMENT) 
        {
            const mimepp::String& theFilename = disposition.filename();

            LPSTR pszAttachContentType;
            LPSTR pszCD;
            LPSTR lpszRealName = new char[256];
            GetContentType(thePart.headers(), &pszAttachContentType);

            // FBS bug 73682 -- Exceptions are at the beginning.  Don't make attachments for those
            if (ctr > 0)
            {
                if (0 == strcmpi(pszAttachContentType, "message/rfc822"))
                {
                    ctr--;
                    continue;
                }
            }
            //

            if((LPSTR)theFilename.length()>0)
            {
                GenerateContentDisposition(&pszCD, (LPSTR)theFilename.c_str());
                strcpy(lpszRealName, (LPSTR)theFilename.c_str());
            }
            else
            {
                char cfilename[64];
                sprintf(cfilename,"attachment-%d",i);
                GenerateContentDisposition(&pszCD, cfilename);
                strcpy(lpszRealName, cfilename);
            }

            // now deal with the encoding
            LPSTR pContent = NULL;
            const mimepp::String &theContent = thePart.body().getString();
            mimepp::String outputString;
            UINT size = 0;

            mimepp::TransferEncodingType& transferEncoding = thePart.headers().contentTransferEncoding();

            if(transferEncoding.asEnum() == mimepp::TransferEncodingType::BASE64) 
            {
                // let's decode the buffer
                mimepp::Base64Decoder decoder;
                outputString = decoder.decode(theContent);
                pContent = (LPSTR)outputString.c_str();
                size = (UINT)outputString.size();
            } 
            else if(transferEncoding.asEnum() == mimepp::TransferEncodingType::QUOTED_PRINTABLE) 
            {
                mimepp::QuotedPrintableDecoder decoder;
                outputString  = decoder.decode(theContent);
                pContent = (LPSTR)outputString.c_str();
                size = (UINT)outputString.size();
            } 
            else 
            {
                pContent = (LPSTR)theContent.c_str();
                size = (UINT)theContent.size();
            }

	    // Save stream to temp file in temp dir.  We'll delete in ZimbraAPI //
            LPCWSTR errMsg;
            HRESULT hr = S_OK;

            wstring wstrTempAppDirPath;
            LPSTR lpszFQFileName = new char[256];
            LPSTR lpszDirName = NULL;
            LPSTR lpszUniqueName = NULL;
            Zimbra::Util::ScopedInterface<IStream> pStream;

            if (!Zimbra::MAPI::Util::GetAppTemporaryDirectory(wstrTempAppDirPath))
            {
                errMsg = FormatExceptionInfo(S_OK, L"GetAppTemporaryDirectory Failed", __FILE__, __LINE__);
                dloge("MAPIRfc2445 -- exception");
                dloge(errMsg);
                return E_FAIL;
            }
            WtoA((LPWSTR)wstrTempAppDirPath.c_str(), lpszDirName);
            WtoA((LPWSTR)Zimbra::MAPI::Util::GetUniqueName().c_str(), lpszUniqueName);
            strcpy(lpszFQFileName, lpszDirName);
            strcat(lpszFQFileName, "\\");
            strcat(lpszFQFileName, lpszUniqueName);

            SafeDelete(lpszDirName);
            SafeDelete(lpszUniqueName);

            // Open stream on file
            if (FAILED(hr = OpenStreamOnFile(MAPIAllocateBuffer, MAPIFreeBuffer, STGM_CREATE |
                    STGM_READWRITE, (LPTSTR)lpszFQFileName, NULL, pStream.getptr())))
            {
                errMsg = FormatExceptionInfo(hr, L"Error: OpenStreamOnFile Failed.", __FILE__, __LINE__);
                dloge("MAPIRfc2445 -- exception");
                dloge(errMsg);
                return hr;
            }

            ULONG nBytesToWrite = size;
            ULONG nBytesWritten = 0;
            LPBYTE pCur = (LPBYTE)pContent;
            while (!FAILED(hr) && nBytesToWrite > 0) 
            {
                hr = pStream->Write(pCur, nBytesToWrite, &nBytesWritten);
                pCur += nBytesWritten;
                nBytesToWrite -= nBytesWritten;
            }
            if (FAILED(hr = pStream->Commit(0)))
            {
                errMsg = FormatExceptionInfo(hr, L"Error: Stream Write Failed.", __FILE__, __LINE__);
                dloge("MAPIRfc2445 -- exception");
                dloge(errMsg);
            }
            ///////////

            // delete all this in MAPIAccessWrap
            AttachmentInfo* pAttachmentInfo = new AttachmentInfo();
            pAttachmentInfo->pszTempFile = lpszFQFileName;
            pAttachmentInfo->pszRealName = lpszRealName;
            pAttachmentInfo->pszContentDisposition = pszCD;
            pAttachmentInfo->pszContentType = pszAttachContentType;
            m_vAttachments.push_back(pAttachmentInfo);
        }
    }
    delete[] pszContentType;
    return S_OK;
}
Пример #8
0
HRESULT MAPIContact::Init()
{
    HRESULT hr = S_OK;
    Zimbra::Util::ScopedBuffer<SPropValue> pPropValMsgClass;

    if (FAILED(hr = HrGetOneProp(m_pMessage, PR_MESSAGE_CLASS, pPropValMsgClass.getptr())))
        throw MAPIContactException(hr, L"Init(): HrGetOneProp Failed.", 
		ERR_MAPI_CONTACT, __LINE__, __FILE__);
    if ((pPropValMsgClass->ulPropTag == PR_MESSAGE_CLASS_W) && (_tcsicmp(
        pPropValMsgClass->Value.LPSZ, L"ipm.distlist") == 0))
        m_bPersonalDL = true;

    // initialize the MAPINAMEID structure GetIDsFromNames requires
    LPMAPINAMEID ppNames[N_NUM_NAMES] = { 0 };

    for (int i = 0; i < N_NUM_NAMES; i++)
    {
        MAPIAllocateBuffer(sizeof (MAPINAMEID), (LPVOID *)&(ppNames[i]));
        ppNames[i]->ulKind = MNID_ID;
        ppNames[i]->lpguid = (LPGUID)(&PS_CONTACT_PROPERTIES);
        ppNames[i]->Kind.lID = nameIds[i];
    }

    // get the real prop tag ID's
    LPSPropTagArray pContactTags = NULL;

    if (FAILED(hr = m_pMessage->GetIDsFromNames(N_NUM_NAMES, ppNames, MAPI_CREATE,
            &pContactTags)))
        throw MAPIContactException(hr, L"Init(): GetIDsFromNames Failed.", 
		ERR_MAPI_CONTACT, __LINE__, __FILE__);
    // give the prop tag ID's a type
    pr_mail1address = SetPropType(pContactTags->aulPropTag[N_MAIL1], PT_TSTRING);
    pr_mail1entryid = SetPropType(pContactTags->aulPropTag[N_MAIL1EID], PT_BINARY);
    pr_mail1type = SetPropType(pContactTags->aulPropTag[N_MAIL1TYPE], PT_TSTRING);
    pr_mail1dispname = SetPropType(pContactTags->aulPropTag[N_MAIL1DISPNAME], PT_TSTRING);
    pr_mail2address = SetPropType(pContactTags->aulPropTag[N_MAIL2], PT_TSTRING);
    pr_mail2entryid = SetPropType(pContactTags->aulPropTag[N_MAIL2EID], PT_BINARY);
    pr_mail2type = SetPropType(pContactTags->aulPropTag[N_MAIL2TYPE], PT_TSTRING);
    pr_mail2dispname = SetPropType(pContactTags->aulPropTag[N_MAIL2DISPNAME], PT_TSTRING);
    pr_mail3address = SetPropType(pContactTags->aulPropTag[N_MAIL3], PT_TSTRING);
    pr_mail3entryid = SetPropType(pContactTags->aulPropTag[N_MAIL3EID], PT_BINARY);
    pr_mail3type = SetPropType(pContactTags->aulPropTag[N_MAIL3TYPE], PT_TSTRING);
    pr_mail3dispname = SetPropType(pContactTags->aulPropTag[N_MAIL3DISPNAME], PT_TSTRING);
    pr_fileas = SetPropType(pContactTags->aulPropTag[N_FILEAS], PT_TSTRING);
    pr_fileasID = SetPropType(pContactTags->aulPropTag[N_FILEAS_ID], PT_LONG);
    pr_business_address_city = SetPropType(pContactTags->aulPropTag[N_BUS_CITY], PT_TSTRING);
    pr_business_address_country = SetPropType(pContactTags->aulPropTag[N_BUS_COUNTRY],
        PT_TSTRING);
    pr_business_address_postal_code = SetPropType(pContactTags->aulPropTag[N_BUS_ZIP],
        PT_TSTRING);
    pr_business_address_state = SetPropType(pContactTags->aulPropTag[N_BUS_STATE], PT_TSTRING);
    pr_business_address_street = SetPropType(pContactTags->aulPropTag[N_BUS_STREET],
        PT_TSTRING);
    pr_contact_user1_idx = SetPropType(pContactTags->aulPropTag[N_CONTACT_USER1_IDX],
        PT_TSTRING);
    pr_contact_user2_idx = SetPropType(pContactTags->aulPropTag[N_CONTACT_USER2_IDX],
        PT_TSTRING);
    pr_contact_user3_idx = SetPropType(pContactTags->aulPropTag[N_CONTACT_USER3_IDX],
        PT_TSTRING);
    pr_contact_user4_idx = SetPropType(pContactTags->aulPropTag[N_CONTACT_USER4_IDX],
        PT_TSTRING);
    pr_contact_oneoffmemebrs = SetPropType(
        pContactTags->aulPropTag[N_CONTACT_ONEOFFMEMEBRS_IDX], PT_MV_BINARY);
    pr_imaddress = SetPropType(pContactTags->aulPropTag[N_IMADDRESS], PT_TSTRING);

    pr_anniversary = SetPropType(pContactTags->aulPropTag[N_ANNIVERSARY], PT_TSTRING);
    // free the memory we allocated on the head
    for (int i = 0; i < N_NUM_NAMES; i++)
        MAPIFreeBuffer(ppNames[i]);
    MAPIFreeBuffer(pContactTags);

    // these are the contact properties we need to get
    SizedSPropTagArray(C_NUM_PROPS, contactProps) = {
        C_NUM_PROPS, {
            PR_CALLBACK_TELEPHONE_NUMBER, PR_CAR_TELEPHONE_NUMBER, PR_COMPANY_NAME,
            pr_mail1address, pr_mail1entryid, pr_mail1type, pr_mail1dispname,
            pr_mail2address, pr_mail2entryid, pr_mail2type, pr_mail2dispname,
            pr_mail3address, pr_mail3entryid, pr_mail3type, pr_mail3dispname, pr_fileas,
            pr_fileasID, PR_GIVEN_NAME, PR_HOME_ADDRESS_CITY, PR_HOME_ADDRESS_COUNTRY,
            PR_HOME_FAX_NUMBER, PR_HOME_TELEPHONE_NUMBER, PR_HOME2_TELEPHONE_NUMBER,
            PR_HOME_ADDRESS_POSTAL_CODE, PR_HOME_ADDRESS_STATE_OR_PROVINCE,
            PR_HOME_ADDRESS_STREET, PR_TITLE, PR_SURNAME, PR_MIDDLE_NAME,
            PR_CELLULAR_TELEPHONE_NUMBER, PR_DISPLAY_NAME_PREFIX, PR_GENERATION,
            // notes is PR_BODY and PR_BODY_HTML
            PR_OTHER_ADDRESS_CITY, PR_OTHER_ADDRESS_COUNTRY, PR_PRIMARY_FAX_NUMBER,     // other fax
            PR_OTHER_TELEPHONE_NUMBER, PR_OTHER_ADDRESS_POSTAL_CODE,
            PR_OTHER_ADDRESS_STATE_OR_PROVINCE, PR_OTHER_ADDRESS_STREET,
            PR_PAGER_TELEPHONE_NUMBER, pr_business_address_city,
            pr_business_address_country, PR_BUSINESS_FAX_NUMBER, PR_OFFICE_TELEPHONE_NUMBER,
            pr_business_address_postal_code, pr_business_address_state,
            pr_business_address_street, PR_BUSINESS_HOME_PAGE, PR_BIRTHDAY,
            pr_contact_user1_idx, pr_contact_user2_idx, pr_contact_user3_idx,
            pr_contact_user4_idx, pr_contact_oneoffmemebrs, pr_imaddress,
            PR_WEDDING_ANNIVERSARY
        }
    };

    ULONG cVals = 0;

    if (FAILED(hr = m_pMessage->GetProps((LPSPropTagArray) & contactProps, fMapiUnicode, &cVals,
            &m_pPropVals)))
        throw MAPIContactException(hr, L"Init(): GetProps Failed.",
		ERR_MAPI_CONTACT, __LINE__, __FILE__);


    // see if there is a file-as id
    LONG zimbraFileAsId = 0;

    if (m_bPersonalDL)                          // PDL's always have a custom file-as
    {
        zimbraFileAsId = 8;
        Type(L"group");
    }
    else if (m_pPropVals[C_FILEASID].ulPropTag == contactProps.aulPropTag[C_FILEASID])
    {
        switch (m_pPropVals[C_FILEASID].Value.l)
        {
        case OFA_LAST_C_FIRST:
            zimbraFileAsId = 1;
            break;
        case OFA_FIRST_LAST:
            zimbraFileAsId = 2;
            break;
        case OFA_COMPANY:
            zimbraFileAsId = 3;
            break;
        case OFA_LAST_C_FIRST_COMPANY:
            zimbraFileAsId = 4;
            break;
        case OFA_COMPANY_LAST_C_FIRST:
            zimbraFileAsId = 6;
            break;
        case OFA_CUSTOM:
            zimbraFileAsId = 8;
            break;
        }
    }
    // process all "String" properties
    if (m_pPropVals[C_CALLBACK_TELEPHONE_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_CALLBACK_TELEPHONE_NUMBER])
        CallbackPhone(m_pPropVals[C_CALLBACK_TELEPHONE_NUMBER].Value.lpszW);
    if (m_pPropVals[C_CAR_TELEPHONE_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_CAR_TELEPHONE_NUMBER])
        CarPhone(m_pPropVals[C_CAR_TELEPHONE_NUMBER].Value.lpszW);
    if (m_pPropVals[C_COMPANY_NAME].ulPropTag == contactProps.aulPropTag[C_COMPANY_NAME])
        Company(m_pPropVals[C_COMPANY_NAME].Value.lpszW);
    if (m_pPropVals[C_FILEAS].ulPropTag == contactProps.aulPropTag[C_FILEAS])
    {
        if (zimbraFileAsId == 8)
        {
            LPWSTR pwszFileAsValue = m_pPropVals[C_FILEAS].Value.lpszW;

            if ((pwszFileAsValue != NULL) && (wcsicmp(pwszFileAsValue, L"") != 0))
            {
                LPWSTR pwszTemp = new WCHAR[wcslen(m_pPropVals[C_FILEAS].Value.lpszW) + 3];

                // there is a legit string for the custom fileas value
                wsprintf(pwszTemp, L"8:%s", pwszFileAsValue);
                FileAs(pwszTemp);
                // PDL's require a nickname
                if (m_bPersonalDL)
                    NickName(m_pPropVals[C_FILEAS].Value.lpszW);
                delete[] pwszTemp;
            }
            else
            {
                LPWSTR pwszNONAME = new WCHAR[wcslen(L"NO_NAME") + 1];

                wsprintf(pwszNONAME, L"%s", L"NO_NAME");

                LPWSTR pwszTemp = new WCHAR[wcslen(pwszNONAME) + 3];

                // there is a legit string for the custom fileas value
                wsprintf(pwszTemp, L"8:%s", pwszNONAME);
                FileAs(pwszTemp);
                // PDL's require a nickname
                if (m_bPersonalDL)
                    NickName(pwszNONAME);
                delete[] pwszTemp;
                delete[] pwszNONAME;
            }
        }
        else if (zimbraFileAsId)
        {
            WCHAR pwszTemp[3];

            _ltow(zimbraFileAsId, pwszTemp, 10);
            FileAs(pwszTemp);
        }
    }
    if (m_pPropVals[C_GIVEN_NAME].ulPropTag == contactProps.aulPropTag[C_GIVEN_NAME])
        FirstName(m_pPropVals[C_GIVEN_NAME].Value.lpszW);
    if (m_pPropVals[C_HOME_ADDRESS_CITY].ulPropTag ==
        contactProps.aulPropTag[C_HOME_ADDRESS_CITY])
        HomeCity(m_pPropVals[C_HOME_ADDRESS_CITY].Value.lpszW);
    if (m_pPropVals[C_HOME_ADDRESS_COUNTRY].ulPropTag ==
        contactProps.aulPropTag[C_HOME_ADDRESS_COUNTRY])
        HomeCountry(m_pPropVals[C_HOME_ADDRESS_COUNTRY].Value.lpszW);
    if (m_pPropVals[C_HOME_FAX_NUMBER].ulPropTag == contactProps.aulPropTag[C_HOME_FAX_NUMBER])
        HomeFax(m_pPropVals[C_HOME_FAX_NUMBER].Value.lpszW);
    if (m_pPropVals[C_HOME_TELEPHONE_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_HOME_TELEPHONE_NUMBER])
        HomePhone(m_pPropVals[C_HOME_TELEPHONE_NUMBER].Value.lpszW);
    if (m_pPropVals[C_HOME2_TELEPHONE_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_HOME2_TELEPHONE_NUMBER])
        HomePhone2(m_pPropVals[C_HOME2_TELEPHONE_NUMBER].Value.lpszW);
    if (m_pPropVals[C_HOME_ADDRESS_POSTAL_CODE].ulPropTag ==
        contactProps.aulPropTag[C_HOME_ADDRESS_POSTAL_CODE])
        HomePostalCode(m_pPropVals[C_HOME_ADDRESS_POSTAL_CODE].Value.lpszW);
    if (m_pPropVals[C_HOME_ADDRESS_STATE_OR_PROVINCE].ulPropTag ==
        contactProps.aulPropTag[C_HOME_ADDRESS_STATE_OR_PROVINCE])
        HomeState(m_pPropVals[C_HOME_ADDRESS_STATE_OR_PROVINCE].Value.lpszW);
    if (m_pPropVals[C_HOME_ADDRESS_STREET].ulPropTag ==
        contactProps.aulPropTag[C_HOME_ADDRESS_STREET])
        HomeStreet(m_pPropVals[C_HOME_ADDRESS_STREET].Value.lpszW);
    if (m_pPropVals[C_TITLE].ulPropTag == contactProps.aulPropTag[C_TITLE])
        JobTitle(m_pPropVals[C_TITLE].Value.lpszW);
    if (m_pPropVals[C_SURNAME].ulPropTag == contactProps.aulPropTag[C_SURNAME])
        LastName(m_pPropVals[C_SURNAME].Value.lpszW);
    if (m_pPropVals[C_MIDDLE_NAME].ulPropTag == contactProps.aulPropTag[C_MIDDLE_NAME])
        MiddleName(m_pPropVals[C_MIDDLE_NAME].Value.lpszW);
    if (m_pPropVals[C_CELLULAR_TELEPHONE_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_CELLULAR_TELEPHONE_NUMBER])
        MobilePhone(m_pPropVals[C_CELLULAR_TELEPHONE_NUMBER].Value.lpszW);
    if (m_pPropVals[C_DISPLAY_NAME_PREFIX].ulPropTag ==
        contactProps.aulPropTag[C_DISPLAY_NAME_PREFIX])
        NamePrefix(m_pPropVals[C_DISPLAY_NAME_PREFIX].Value.lpszW);
    if (m_pPropVals[C_GENERATION].ulPropTag == contactProps.aulPropTag[C_GENERATION])
        NameSuffix(m_pPropVals[C_GENERATION].Value.lpszW);
    if (m_pPropVals[C_OTHER_ADDRESS_CITY].ulPropTag ==
        contactProps.aulPropTag[C_OTHER_ADDRESS_CITY])
        OtherCity(m_pPropVals[C_OTHER_ADDRESS_CITY].Value.lpszW);
    if (m_pPropVals[C_OTHER_ADDRESS_COUNTRY].ulPropTag ==
        contactProps.aulPropTag[C_OTHER_ADDRESS_COUNTRY])
        OtherCountry(m_pPropVals[C_OTHER_ADDRESS_COUNTRY].Value.lpszW);
    if (m_pPropVals[C_PRIMARY_FAX_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_PRIMARY_FAX_NUMBER])
        OtherFax(m_pPropVals[C_PRIMARY_FAX_NUMBER].Value.lpszW);
    if (m_pPropVals[C_OTHER_TELEPHONE_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_OTHER_TELEPHONE_NUMBER])
        OtherPhone(m_pPropVals[C_OTHER_TELEPHONE_NUMBER].Value.lpszW);
    if (m_pPropVals[C_OTHER_ADDRESS_POSTAL_CODE].ulPropTag ==
        contactProps.aulPropTag[C_OTHER_ADDRESS_POSTAL_CODE])
        OtherPostalCode(m_pPropVals[C_OTHER_ADDRESS_POSTAL_CODE].Value.lpszW);
    if (m_pPropVals[C_OTHER_ADDRESS_STATE_OR_PROVINCE].ulPropTag ==
        contactProps.aulPropTag[C_OTHER_ADDRESS_STATE_OR_PROVINCE])
        OtherState(m_pPropVals[C_OTHER_ADDRESS_STATE_OR_PROVINCE].Value.lpszW);
    if (m_pPropVals[C_OTHER_ADDRESS_STREET].ulPropTag ==
        contactProps.aulPropTag[C_OTHER_ADDRESS_STREET])
        OtherStreet(m_pPropVals[C_OTHER_ADDRESS_STREET].Value.lpszW);
    if (m_pPropVals[C_PAGER_TELEPHONE_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_PAGER_TELEPHONE_NUMBER])
        Pager(m_pPropVals[C_PAGER_TELEPHONE_NUMBER].Value.lpszW);
    if (m_pPropVals[C_BUSINESS_ADDRESS_CITY].ulPropTag ==
        contactProps.aulPropTag[C_BUSINESS_ADDRESS_CITY])
        WorkCity(m_pPropVals[C_BUSINESS_ADDRESS_CITY].Value.lpszW);
    if (m_pPropVals[C_BUSINESS_ADDRESS_COUNTRY].ulPropTag ==
        contactProps.aulPropTag[C_BUSINESS_ADDRESS_COUNTRY])
        WorkCountry(m_pPropVals[C_BUSINESS_ADDRESS_COUNTRY].Value.lpszW);
    if (m_pPropVals[C_BUSINESS_FAX_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_BUSINESS_FAX_NUMBER])
        WorkFax(m_pPropVals[C_BUSINESS_FAX_NUMBER].Value.lpszW);
    if (m_pPropVals[C_OFFICE_TELEPHONE_NUMBER].ulPropTag ==
        contactProps.aulPropTag[C_OFFICE_TELEPHONE_NUMBER])
        WorkPhone(m_pPropVals[C_OFFICE_TELEPHONE_NUMBER].Value.lpszW);
    if (m_pPropVals[C_BUSINESS_ADDRESS_POSTAL_CODE].ulPropTag ==
        contactProps.aulPropTag[C_BUSINESS_ADDRESS_POSTAL_CODE])
        WorkPostalCode(m_pPropVals[C_BUSINESS_ADDRESS_POSTAL_CODE].Value.lpszW);
    if (m_pPropVals[C_BUSINESS_ADDRESS_STATE].ulPropTag ==
        contactProps.aulPropTag[C_BUSINESS_ADDRESS_STATE])
        WorkState(m_pPropVals[C_BUSINESS_ADDRESS_STATE].Value.lpszW);
    if (m_pPropVals[C_BUSINESS_ADDRESS_STREET].ulPropTag ==
        contactProps.aulPropTag[C_BUSINESS_ADDRESS_STREET])
        WorkStreet(m_pPropVals[C_BUSINESS_ADDRESS_STREET].Value.lpszW);
    if (m_pPropVals[C_BUSINESS_HOME_PAGE].ulPropTag ==
        contactProps.aulPropTag[C_BUSINESS_HOME_PAGE])
        WorkURL(m_pPropVals[C_BUSINESS_HOME_PAGE].Value.lpszW);
    if (m_pPropVals[C_CONTACT_USER1_IDX].ulPropTag ==
        contactProps.aulPropTag[C_CONTACT_USER1_IDX])
        UserField1(m_pPropVals[C_CONTACT_USER1_IDX].Value.lpszW);
    if (m_pPropVals[C_CONTACT_USER2_IDX].ulPropTag ==
        contactProps.aulPropTag[C_CONTACT_USER2_IDX])
        UserField2(m_pPropVals[C_CONTACT_USER2_IDX].Value.lpszW);
    if (m_pPropVals[C_CONTACT_USER3_IDX].ulPropTag ==
        contactProps.aulPropTag[C_CONTACT_USER3_IDX])
        UserField3(m_pPropVals[C_CONTACT_USER3_IDX].Value.lpszW);
    if (m_pPropVals[C_CONTACT_USER4_IDX].ulPropTag ==
        contactProps.aulPropTag[C_CONTACT_USER4_IDX])
        UserField4(m_pPropVals[C_CONTACT_USER4_IDX].Value.lpszW);
    if (m_pPropVals[C_BIRTHDAY].ulPropTag == contactProps.aulPropTag[C_BIRTHDAY])
    {
        SYSTEMTIME st = { 0 };

        FileTimeToSystemTime(&(m_pPropVals[C_BIRTHDAY].Value.ft), &st);

        // We get PR_BIRTHDAY in UTC so let's convert it into local time
        TIME_ZONE_INFORMATION tzInfo = { 0 };

        GetTimeZoneInformation(&tzInfo);
        SystemTimeToTzSpecificLocalTime(&tzInfo, &st, &st);

        TCHAR pszBDay[11];

        swprintf(pszBDay, 11, _T("%4d-%02d-%02d"), st.wYear, st.wMonth, st.wDay);

        Birthday(pszBDay);
    }
    if (m_pPropVals[C_ANNIVERSARY].ulPropTag == contactProps.aulPropTag[C_ANNIVERSARY])
    {
        SYSTEMTIME st = { 0 };

        FileTimeToSystemTime(&(m_pPropVals[C_ANNIVERSARY].Value.ft), &st);

        // We get PR_ANNIVERSARY in UTC so let's convert it into local time
        TIME_ZONE_INFORMATION tzInfo = { 0 };

        GetTimeZoneInformation(&tzInfo);
        SystemTimeToTzSpecificLocalTime(&tzInfo, &st, &st);

        TCHAR pszAnniv[11];

        swprintf(pszAnniv, 11, _T("%4d-%02d-%02d"), st.wYear, st.wMonth, st.wDay);

        Anniversary(pszAnniv);
    }

    // email 1
    RECIP_INFO tempRecip;

    if ((m_pPropVals[C_MAIL1TYPE].ulPropTag == contactProps.aulPropTag[C_MAIL1TYPE]) &&
        (m_pPropVals[C_MAIL1ADDRESS].ulPropTag == contactProps.aulPropTag[C_MAIL1ADDRESS]))
    {
        if (wcscmp(m_pPropVals[C_MAIL1TYPE].Value.lpszW, L"SMTP") == 0)
        {
            Email(m_pPropVals[C_MAIL1ADDRESS].Value.lpszW);
        }
        else if (wcscmp(m_pPropVals[C_MAIL1TYPE].Value.lpszW, L"EX") == 0)
        {
            tempRecip.pAddrType = m_pPropVals[C_MAIL1TYPE].Value.lpszW;
            tempRecip.pEmailAddr = m_pPropVals[C_MAIL1ADDRESS].Value.lpszW;
            tempRecip.cbEid = m_pPropVals[C_MAIL1EID].Value.bin.cb;
            tempRecip.pEid = (LPENTRYID)(m_pPropVals[C_MAIL1EID].Value.bin.lpb);

            wstring strSenderEmail(_TEXT(""));
            HRESULT hr = Zimbra::MAPI::Util::HrMAPIGetSMTPAddress(*m_session, tempRecip,
                strSenderEmail);

            if (hr != S_OK)
                Email(m_pPropVals[C_MAIL1DISPNAME].Value.lpszW);

            else
                Email((LPTSTR)strSenderEmail.c_str());
        }
    }
    // email 2
    if ((m_pPropVals[C_MAIL2TYPE].ulPropTag == contactProps.aulPropTag[C_MAIL2TYPE]) &&
        (m_pPropVals[C_MAIL2ADDRESS].ulPropTag == contactProps.aulPropTag[C_MAIL2ADDRESS]))
    {
        if (wcscmp(m_pPropVals[C_MAIL2TYPE].Value.lpszW, L"SMTP") == 0)
        {
            Email2(m_pPropVals[C_MAIL2ADDRESS].Value.lpszW);
        }
        else if (wcscmp(m_pPropVals[C_MAIL2TYPE].Value.lpszW, L"EX") == 0)
        {
            tempRecip.pAddrType = m_pPropVals[C_MAIL2TYPE].Value.lpszW;
            tempRecip.pEmailAddr = m_pPropVals[C_MAIL2ADDRESS].Value.lpszW;
            tempRecip.cbEid = m_pPropVals[C_MAIL2EID].Value.bin.cb;
            tempRecip.pEid = (LPENTRYID)(m_pPropVals[C_MAIL2EID].Value.bin.lpb);

            wstring strSenderEmail(_TEXT(""));
            HRESULT hr = Zimbra::MAPI::Util::HrMAPIGetSMTPAddress(*m_session, tempRecip,
                strSenderEmail);

            if (hr != S_OK)
                Email(m_pPropVals[C_MAIL2DISPNAME].Value.lpszW);

            else
                Email2((LPTSTR)strSenderEmail.c_str());
        }
    }
    // email 3
    if ((m_pPropVals[C_MAIL3TYPE].ulPropTag == contactProps.aulPropTag[C_MAIL3TYPE]) &&
        (m_pPropVals[C_MAIL3ADDRESS].ulPropTag == contactProps.aulPropTag[C_MAIL3ADDRESS]))
    {
        if (wcscmp(m_pPropVals[C_MAIL3TYPE].Value.lpszW, L"SMTP") == 0)
        {
            Email3(m_pPropVals[C_MAIL3ADDRESS].Value.lpszW);
        }
        else if (wcscmp(m_pPropVals[C_MAIL3TYPE].Value.lpszW, L"EX") == 0)
        {
            tempRecip.pAddrType = m_pPropVals[C_MAIL3TYPE].Value.lpszW;
            tempRecip.pEmailAddr = m_pPropVals[C_MAIL3ADDRESS].Value.lpszW;
            tempRecip.cbEid = m_pPropVals[C_MAIL3EID].Value.bin.cb;
            tempRecip.pEid = (LPENTRYID)(m_pPropVals[C_MAIL3EID].Value.bin.lpb);

            wstring strSenderEmail(_TEXT(""));
            HRESULT hr = Zimbra::MAPI::Util::HrMAPIGetSMTPAddress(*m_session, tempRecip,
                strSenderEmail);

            if (hr != S_OK)
                Email(m_pPropVals[C_MAIL3DISPNAME].Value.lpszW);

            else
                Email3((LPTSTR)strSenderEmail.c_str());
        }
    }
    if (m_pPropVals[C_IMADDRESS].ulPropTag == contactProps.aulPropTag[C_IMADDRESS])
        IMAddress1(m_pPropVals[C_IMADDRESS].Value.lpszW);
    // add the 'notes' section
    if (m_mapiMessage->HasTextPart())
    {
        LPTSTR pBody = NULL;
        UINT nText = 0;

        m_mapiMessage->TextBody(&pBody, nText);

        LPTSTR psz = pBody;

        if (psz)
        {
            const char SPACE = ' ', TAB = '\t', CR = 0x0d, LF = 0x0a;

            while (*psz)
            {
                // Replace control characters with space
                // Exclude carriage return and new line characters while doing the same
                if ((*psz < SPACE) && (*psz != CR) && (*psz != LF))
                    *psz = _T(' ');
                psz++;
            }

            // We'll add the body only if it has data other than white spaces and new lines
            bool bHasValidChars = false;

            psz = pBody;
            while (*psz)
            {
                if ((*psz == SPACE) || (*psz == TAB) || (*psz == CR) || (*psz == LF))
                {
                    psz++;
                    continue;
                }
                else
                {
                    bHasValidChars = true;
                    break;
                }
            }
            if (bHasValidChars)
                Notes(pBody);
            MAPIFreeBuffer(pBody);
        }
    }

	// if its a distribution list, add the dist list members to the property
	wstring strInvalidGroupContacts;
    if (m_bPersonalDL)
    {
        std::wstring dlist = L"";

        if (m_pPropVals[C_ONEOFFMEMEBRS_IDX].ulPropTag ==
            contactProps.aulPropTag[C_ONEOFFMEMEBRS_IDX])
        {
            bool bFirst = true;

            for (ULONG i = 0; i < m_pPropVals[C_ONEOFFMEMEBRS_IDX].Value.MVbin.cValues; i++)
            {
                DWORD dwObjType;
                SBinary &bin = m_pPropVals[C_ONEOFFMEMEBRS_IDX].Value.MVbin.lpbin[i];
                IMailUser *pUser = NULL;

                hr = m_session->OpenEntry(bin.cb, (LPENTRYID)bin.lpb, NULL, 0, &dwObjType,
                    (LPUNKNOWN *)&pUser);
                if (FAILED(hr) || !pUser)
                    continue;

                LPSPropValue pDNProp = NULL;
                LPSPropValue pAddrProp = NULL;
                std::wstring user = L"";
                BOOL bIsInvalidContact = TRUE;

                HrGetOneProp(pUser, PR_DISPLAY_NAME_W, &pDNProp);
                HrGetOneProp(pUser, PR_EMAIL_ADDRESS_W, &pAddrProp);
                if (pDNProp && (pDNProp->ulPropTag == PR_DISPLAY_NAME_W) && wcslen(
                    pDNProp->Value.lpszW))
                    user += pDNProp->Value.lpszW;
                if (pAddrProp && (pAddrProp->ulPropTag == PR_EMAIL_ADDRESS_W) && wcslen(
                    pAddrProp->Value.lpszW))
                {
                    std::wstring temp = pAddrProp->Value.lpszW;

                    if (temp.find(L'@') != std::wstring::npos)
                        bIsInvalidContact = FALSE;
                    if (!user.empty())
                        user += L" ";
                    user += L"<";
                    user += temp;
                    user += L">";
                }
                if (bIsInvalidContact)
                {
                    if (!user.empty())
                    {
						if (!strInvalidGroupContacts.empty())
                            strInvalidGroupContacts += _T(", ");
                        strInvalidGroupContacts += user.c_str();
                    }
                }
                else
                {
                    if (bFirst)
                        bFirst = false;
                    else
                        dlist += L",";
                    dlist += user;
                }
                pUser->Release();
                MAPIFreeBuffer(pDNProp);
                MAPIFreeBuffer(pAddrProp);
            }
        }
		//set DL values
		DList((LPTSTR)dlist.c_str());
	}

	//user define props
	if (!m_bPersonalDL)
	{
		LPMAPINAMEID FAR *lppPropNames = NULL;
		LPSPropTagArray tagArray;
		ULONG lCount = 0;

		hr = m_pMessage->GetPropList(MAPI_UNICODE, &tagArray);
		if (hr == S_OK)
		{
			hr = m_pMessage->GetNamesFromIDs(&tagArray, (LPGUID)&PS_PUBLIC_STRINGS, 0, &lCount,
				&lppPropNames);
			if (SUCCEEDED(hr))
			{
				WCHAR wszProps2GUID[40] = { 0 };
				Zimbra::Util::Guid nameProps2Guid(OUTLOOK_NAME_PROPS_GUID_2);

				nameProps2Guid.toString(wszProps2GUID);

				WCHAR wszContactPropGUID[40] = { 0 };
				WCHAR wszVal[1024]={0};                 

				for (ULONG i = 0; i < lCount; i++)
				{
					Zimbra::Util::ScopedBuffer<SPropValue> pPropVal;

					hr = HrGetOneProp(m_pMessage, tagArray->aulPropTag[i], pPropVal.getptr());
                                        if (lppPropNames[i] != NULL)    // FBS bug 71786 -- 3/20/12
                                        {
					    if (lppPropNames[i]->ulKind == MNID_STRING)
					    {
						    Zimbra::Util::Guid propGuid(*lppPropNames[i]->lpguid);

						    propGuid.toString(wszContactPropGUID);
						    if (lstrcmpiW(wszContactPropGUID, wszProps2GUID) == 0)
						    {
							    LPWSTR szPropName = lppPropNames[i]->Kind.lpwstrName;

							    // now format a string depending on the type
							    ULONG ulPropType = PROP_TYPE(pPropVal->ulPropTag);
							    BOOL bSetAttribute = TRUE;

							    switch (ulPropType)
							    {
							    case PT_UNICODE:
								    wcscpy(wszVal, pPropVal->Value.lpszW);
								    break;

							    case PT_SYSTIME:
							    {
								    SYSTEMTIME sysTime = { 0 };

								    if (FileTimeToSystemTime(&(pPropVal->Value.ft), &sysTime))
								    {
									    TIME_ZONE_INFORMATION tzInfo = { 0 };

									    GetTimeZoneInformation(&tzInfo);
									    SystemTimeToTzSpecificLocalTime(&tzInfo, &sysTime, &sysTime);
									    wsprintf(wszVal, L"%4d-%02d-%02d", sysTime.wYear,
										    sysTime.wMonth, sysTime.wDay);
								    }
								    break;
							    }

							    case PT_LONG:
								    wsprintf(wszVal, L"%d", pPropVal->Value.l);
								    break;

							    case PT_DOUBLE:
							    {
								    CHAR tmp[36];

								    _gcvt(pPropVal->Value.dbl, 6, tmp);

								    LPWSTR wszTmp = Zimbra::Util::AnsiiToUnicode(tmp);

								    wcscpy(wszVal, wszTmp);
								    break;
							    }

							    case PT_BOOLEAN:
								    if (pPropVal->Value.b)
									    wcscpy(wszVal, L"TRUE");
								    else
									    wcscpy(wszVal, L"FALSE");
								    break;

							    case PT_CURRENCY:
							    {
								    LONGLONG lCurrency;
								    CURRENCY currency;

								    currency = pPropVal->Value.cur;
								    lCurrency = currency.int64;
								    lCurrency = lCurrency / 10000;
								    wsprintf(wszVal, L"$%I64d", lCurrency);
								    break;
							    }

							    default:                // can't deal with these other types 
								    bSetAttribute = FALSE;
								    //LOG("%hs: MAPI type %0x not supported: user defined field %s will not be synced"),
								    //		__FUNCTION__, ulPropType, szPropName);
							    }

							    ContactUDFields cudf;
							    cudf.Name = szPropName;
							    cudf.value = wszVal;
							    AddUserDefinedField(cudf);
						    }
					    }
                                        }
				}
				MAPIFreeBuffer(lppPropNames);
			}
			MAPIFreeBuffer(tagArray);
		}
	}

    // Save image path
    wstring wstrImagePath;

    if (m_mapiMessage->HasAttach())
    {
        if (!FAILED(hr = GetContactImage(wstrImagePath)))
            ContactImagePath((LPTSTR)wstrImagePath.c_str());
    }
    return S_OK;
}
HRESULT MAPIAppointment::InitNamedPropsForAppt()
{
    // init named props
    nameIds[0] = 0x0023;
    nameIds[1] = 0x820D;
    nameIds[2] = 0x820E;
    nameIds[3] = 0x8208;
    nameIds[4] = 0x8205;
    nameIds[5] = 0x8215;
    nameIds[6] = 0x8223;
    nameIds[7] = 0x8216;
    nameIds[8] = 0x8234;
    nameIds[9] = 0x8218;
    nameIds[10] = 0x8228;

    nameIdsC[0] = 0x8501;
    nameIdsC[1] = 0x8506;
	nameIdsC[2] = 0x8503;

    HRESULT hr = S_OK;
    Zimbra::Util::ScopedBuffer<SPropValue> pPropValMsgClass;

    if (FAILED(hr = HrGetOneProp(m_pMessage, PR_MESSAGE_CLASS, pPropValMsgClass.getptr())))
        throw MAPIAppointmentException(hr, L"InitNamedPropsForAppt(): HrGetOneProp Failed.", 
		ERR_MAPI_APPOINTMENT, __LINE__, __FILE__);

    // initialize the MAPINAMEID structure GetIDsFromNames requires
    LPMAPINAMEID ppNames[N_NUMAPPTPROPS] = { 0 };
    for (int i = 0; i < N_NUMAPPTPROPS; i++)
    {
        MAPIAllocateBuffer(sizeof (MAPINAMEID), (LPVOID *)&(ppNames[i]));
        ppNames[i]->ulKind = MNID_ID;
        ppNames[i]->lpguid = (i == N_UID) ? (LPGUID)(&PS_OUTLOOK_MTG) : (LPGUID)(&PS_OUTLOOK_APPT);
        ppNames[i]->Kind.lID = nameIds[i];
    }

    LPMAPINAMEID ppNamesC[N_NUMCOMMONPROPS] = { 0 };
    for (int i = 0; i < N_NUMCOMMONPROPS; i++)
    {
        MAPIAllocateBuffer(sizeof (MAPINAMEID), (LPVOID *)&(ppNamesC[i]));
        ppNamesC[i]->ulKind = MNID_ID;
        ppNamesC[i]->lpguid = (LPGUID)(&PS_OUTLOOK_COMMON);
        ppNamesC[i]->Kind.lID = nameIdsC[i];
    }

    // get the real prop tag ID's
    LPSPropTagArray pAppointmentTags = NULL;
    LPSPropTagArray pAppointmentTagsC = NULL;

    if (FAILED(hr = m_pMessage->GetIDsFromNames(N_NUMAPPTPROPS, ppNames, MAPI_CREATE,
            &pAppointmentTags)))
        throw MAPIAppointmentException(hr, L"Init(): GetIDsFromNames on pAppointmentTags Failed.", 
		ERR_MAPI_APPOINTMENT, __LINE__, __FILE__);

    if (FAILED(hr = m_pMessage->GetIDsFromNames(N_NUMCOMMONPROPS, ppNamesC, MAPI_CREATE,
            &pAppointmentTagsC)))
        throw MAPIAppointmentException(hr, L"Init(): GetIDsFromNames on pAppointmentTagsC Failed.", 
		ERR_MAPI_APPOINTMENT, __LINE__, __FILE__);

    // give the prop tag ID's a type
    pr_clean_global_objid = SetPropType(pAppointmentTags->aulPropTag[N_UID], PT_BINARY);
    pr_appt_start = SetPropType(pAppointmentTags->aulPropTag[N_APPTSTART], PT_SYSTIME);
    pr_appt_end = SetPropType(pAppointmentTags->aulPropTag[N_APPTEND], PT_SYSTIME);
    pr_location = SetPropType(pAppointmentTags->aulPropTag[N_LOCATION], PT_TSTRING);
    pr_busystatus = SetPropType(pAppointmentTags->aulPropTag[N_BUSYSTATUS], PT_LONG);
    pr_allday = SetPropType(pAppointmentTags->aulPropTag[N_ALLDAY], PT_BOOLEAN);
    pr_isrecurring = SetPropType(pAppointmentTags->aulPropTag[N_ISRECUR], PT_BOOLEAN);
    pr_recurstream = SetPropType(pAppointmentTags->aulPropTag[N_RECURSTREAM], PT_BINARY);
    pr_timezoneid = SetPropType(pAppointmentTags->aulPropTag[N_TIMEZONEID], PT_TSTRING);
    pr_responsestatus = SetPropType(pAppointmentTags->aulPropTag[N_RESPONSESTATUS], PT_LONG);
    pr_exceptionreplacetime = SetPropType(pAppointmentTags->aulPropTag[N_EXCEPTIONREPLACETIME], PT_SYSTIME);
    pr_reminderminutes = SetPropType(pAppointmentTagsC->aulPropTag[N_REMINDERMINUTES], PT_LONG);
	
    pr_private = SetPropType(pAppointmentTagsC->aulPropTag[N_PRIVATE], PT_BOOLEAN);
	pr_reminderset = SetPropType(pAppointmentTagsC->aulPropTag[N_REMINDERSET], PT_BOOLEAN);
    // free the memory we allocated on the head
    for (int i = 0; i < N_NUMAPPTPROPS; i++)
    {
        MAPIFreeBuffer(ppNames[i]);
    }
    for (int i = 0; i < N_NUMCOMMONPROPS; i++)
    {
        MAPIFreeBuffer(ppNamesC[i]);
    }
    MAPIFreeBuffer(pAppointmentTags);
    MAPIFreeBuffer(pAppointmentTagsC);

    //MAPIAppointment::m_bNamedPropsInitialized = true;

    return S_OK;
}