ultimatepp/bazaar/MAPIEx/MAPIMessage.cpp
koldo d08dae7b40 MAPIEx: Updated interface
git-svn-id: svn://ultimatepp.org/upp/trunk@6416 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2013-10-11 19:54:08 +00:00

497 lines
No EOL
15 KiB
C++

#ifdef _WIN32
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// File: MAPIMessage.cpp
// Description: MAPI Message class wrapper
//
// Copyright (C) 2005-2011, Noel Dillabough
//
// This source code is free to use and modify provided this notice remains intact and that any enhancements
// or bug fixes are posted to the CodeProject page hosting this class for the community to benefit.
//
// Usage: see the CodeProject article at http://www.codeproject.com/internet/CMapiEx.asp
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Ported to U++ Framework by Koldo. See License.txt file
#include "MAPIEx.h"
#include "MapiUtil.h"
#include <imessage.h>
const GUID CLSID_MailMessage={ 0x00020D0B, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
#ifndef _WIN32_WCE
#define INITGUID
#define USES_IID_IMessage
#include <InitGuid.h>
#include <MAPIGuid.h>
#endif
extern "C" {
STDAPI_(void) CloseIMsgSession(LPMSGSESS lpMsgSess);
}
/////////////////////////////////////////////////////////////
// MAPIMessage
MAPIMessage::MAPIMessage() {
m_pRecipients = NULL;
}
MAPIMessage::~MAPIMessage() {
Close();
}
bool MAPIMessage::Open(MAPIEx* pMAPI, SBinary entryID) {
if(!MAPIObject::Open(pMAPI,entryID))
return false;
m_strSenderName = GetPropertyString(PR_SENDER_NAME);
FillSenderEmail();
m_strSubject = GetPropertyString(PR_SUBJECT);
return true;
}
void MAPIMessage::Close() {
RELEASE(m_pRecipients);
MAPIObject::Close();
}
String MAPIMessage::GetHeader() {
return GetPropertyString(PR_TRANSPORT_MESSAGE_HEADERS);
}
void MAPIMessage::FillSenderEmail() {
String strAddrType = GetPropertyString(PR_SENDER_ADDRTYPE);
m_strSenderEmail = GetPropertyString(PR_SENDER_EMAIL_ADDRESS);
// for Microsoft Exchange server internal mails we want to try to resolve the SMTP email address
if(strAddrType == "EX") {
LPSPropValue pProp;
if(GetProperty(PR_SENDER_ENTRYID, pProp)==S_OK) {
if(m_pMAPI)
m_pMAPI->GetExEmail(pProp->Value.bin, m_strSenderEmail);
MAPIFreeBuffer(pProp);
}
}
}
Time MAPIMessage::GetTime(ULONG property) {
SYSTEMTIME st;
LPSPropValue pProp;
if(GetProperty(property, pProp) == S_OK) {
FILETIME tmLocal;
FileTimeToLocalFileTime(&pProp->Value.ft, &tmLocal);
FileTimeToSystemTime(&tmLocal, &st);
MAPIFreeBuffer(pProp);
return MAPIEx::GetSystemTime(st);
}
return Null;
}
String MAPIMessage::GetTo() {
return GetPropertyString(PR_DISPLAY_TO);
}
String MAPIMessage::GetCC() {
return GetPropertyString(PR_DISPLAY_CC);
}
String MAPIMessage::GetBCC() {
return GetPropertyString(PR_DISPLAY_BCC);
}
int MAPIMessage::GetMessageStatus() {
return GetPropertyValue(PR_MSG_STATUS, 0);
}
int MAPIMessage::GetPriority() {
return GetPropertyValue(PR_PRIORITY, PRIO_NONURGENT);
}
DWORD MAPIMessage::GetSize() {
return GetPropertyValue(PR_MESSAGE_SIZE, 0);
}
bool MAPIMessage::GetRecipients() {
if(!Message())
return false;
RELEASE(m_pRecipients);
if(Message()->GetRecipientTable(MAPIEx::cm_nMAPICode, &m_pRecipients) != S_OK)
return false;
const int nProperties = RECIPIENT_COLS;
SizedSPropTagArray(nProperties, Columns)={nProperties,{PR_RECIPIENT_TYPE, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_ADDRTYPE, PR_ENTRYID }};
return (m_pRecipients->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK);
}
bool MAPIMessage::GetNextRecipient(String& strName, String& strEmail, int &nType) {
if(!m_pRecipients)
return false;
LPSRowSet pRows = NULL;
bool bResult = false;
if(m_pRecipients->QueryRows(1, 0, &pRows) == S_OK) {
if(pRows->cRows) {
nType = pRows->aRow[0].lpProps[PROP_RECIPIENT_TYPE].Value.ul;
strName = MAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_RECIPIENT_NAME]);
// for Microsoft Exchange server internal mails we want to try to resolve the SMTP email address
String strAddrType = MAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_ADDR_TYPE]);
if(strAddrType == "EX") {
if(m_pMAPI)
m_pMAPI->GetExEmail(pRows->aRow[0].lpProps[PROP_ENTRYID].Value.bin, strEmail);
} else
strEmail = MAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_RECIPIENT_EMAIL]);
bResult = true;
}
FreeProws(pRows);
}
return bResult;
}
String MAPIMessage::GetReplyTo() {
String strEmail;
bool bResult = false;
LPSPropValue prop;
if(GetProperty(PR_REPLY_RECIPIENT_ENTRIES, prop) == S_OK) {
LPFLATENTRYLIST pReplyEntryList = (LPFLATENTRYLIST)prop->Value.bin.lpb;
if(pReplyEntryList->cEntries > 0) {
LPFLATENTRY pReplyEntry = (LPFLATENTRY)pReplyEntryList->abEntries;
SBinary entryID;
entryID.cb = pReplyEntry->cb;
entryID.lpb = pReplyEntry->abEntry;
bResult = m_pMAPI->GetExEmail(entryID, strEmail);
}
MAPIFreeBuffer(prop);
}
if (bResult)
return strEmail;
else
return String();
}
// nPriority defaults to IMPORTANCE_NORMAL, IMPORTANCE_HIGH or IMPORTANCE_LOW also valid
bool MAPIMessage::Create(MAPIEx &mapi, MAPIFolder &folder, int nPriority, bool bSaveToSentFolder) {
if(!MAPIObject::Create(mapi, folder))
return false;
SPropValue prop;
SetMessageFlags(MSGFLAG_UNSENT | MSGFLAG_FROMME);
LPSPropValue pProp = NULL;
ULONG cValues = 0;
ULONG rgTags[] = { 1, PR_IPM_SENTMAIL_ENTRYID };
if(m_pMAPI->GetMessageStore()->GetProps((LPSPropTagArray) rgTags, MAPIEx::cm_nMAPICode, &cValues, &pProp)==S_OK) {
if(bSaveToSentFolder) {
prop.ulPropTag = PR_SENTMAIL_ENTRYID;
prop.Value.bin = pProp[0].Value.bin;
} else {
prop.ulPropTag = PR_DELETE_AFTER_SUBMIT;
prop.Value.b = true;
}
Message()->SetProps(1, &prop, NULL);
SetEntryID(&(pProp[0].Value.bin));
MAPIFreeBuffer(pProp);
}
if(nPriority != IMPORTANCE_NORMAL) {
prop.ulPropTag = PR_IMPORTANCE;
prop.Value.l = nPriority;
Message()->SetProps(1, &prop, NULL);
}
SetMessageClass("IPM.Note");
#ifdef _WIN32_WCE
prop.ulPropTag = PR_MSG_STATUS;
prop.Value.ul = MSGSTATUS_RECTYPE_SMTP;
Message()->SetProps(1, &prop, NULL);
#endif
return true;
}
bool MAPIMessage::IsUnread() {
return (!(GetMessageFlags()&MSGFLAG_READ));
}
bool MAPIMessage::MarkAsRead(bool bRead) {
#ifdef _WIN32_WCE
int ulMessageFlags = GetMessageFlags();
if(bRead) ulMessageFlags |= MSGFLAG_READ;
else ulMessageFlags &= ~MSGFLAG_READ;
return SetMessageFlags(ulMessageFlags);
#else
return (Message()->SetReadFlag(bRead ? MSGFLAG_READ : CLEAR_READ_FLAG)==S_OK);
#endif
}
bool MAPIMessage::AddRecipients(LPADRLIST pAddressList) {
HRESULT hr = E_INVALIDARG;
#ifdef _WIN32_WCE
hr = Message()->ModifyRecipients(MODRECIP_ADD, pAddressList);
#else
LPADRBOOK pAddressBook;
if(m_pMAPI->GetSession()->OpenAddressBook(0, NULL, AB_NO_DIALOG, &pAddressBook) != S_OK)
return false;
if(pAddressBook->ResolveName(0, MAPIEx::cm_nMAPICode, NULL, pAddressList) == S_OK)
hr = Message()->ModifyRecipients(MODRECIP_ADD, pAddressList);
RELEASE(pAddressBook);
#endif
return (hr == S_OK);
}
// AddrType only needed by Windows CE, use SMTP, or SMS etc, default NULL will not set PR_ADDRTYPE
bool MAPIMessage::AddRecipient(const String &email, int nType, const char* szAddrType) {
if(!Message() || !m_pMAPI)
return false;
int nBufSize=CbNewADRLIST(1);
LPADRLIST pAddressList = NULL;
MAPIAllocateBuffer(nBufSize, (LPVOID FAR*)&pAddressList);
memset(pAddressList, 0, nBufSize);
int nProperties = 3;
if(szAddrType==NULL)
nProperties--;
pAddressList->cEntries=1;
pAddressList->aEntries[0].ulReserved1 = 0;
pAddressList->aEntries[0].cValues=nProperties;
MAPIAllocateBuffer(sizeof(SPropValue)*nProperties, (LPVOID FAR*)&pAddressList->aEntries[0].rgPropVals);
memset(pAddressList->aEntries[0].rgPropVals, 0, sizeof(SPropValue)*nProperties);
pAddressList->aEntries[0].rgPropVals[0].ulPropTag = PR_RECIPIENT_TYPE;
pAddressList->aEntries[0].rgPropVals[0].Value.ul = nType;
#ifdef _WIN32_WCE
pAddressList->aEntries[0].rgPropVals[1].ulPropTag = PR_EMAIL_ADDRESS;
pAddressList->aEntries[0].rgPropVals[1].Value.LPSZ = (TCHAR*)szEmail;
#else
pAddressList->aEntries[0].rgPropVals[1].ulPropTag = PR_DISPLAY_NAME;
pAddressList->aEntries[0].rgPropVals[1].Value.LPSZ = (TCHAR*)(email.Begin());
#endif
if(szAddrType != NULL) {
pAddressList->aEntries[0].rgPropVals[2].ulPropTag = PR_ADDRTYPE;
pAddressList->aEntries[0].rgPropVals[2].Value.LPSZ = (TCHAR*)szAddrType;
}
bool bResult = AddRecipients(pAddressList);
MAPIEx::ReleaseAddressList(pAddressList);
return bResult;
}
void MAPIMessage::SetSubject(const String &subject) {
m_strSubject = subject;
SetPropertyString(PR_SUBJECT, subject);
}
void MAPIMessage::SetSender(const String &senderName, const String &senderEmail) {
m_strSenderName = senderName;
m_strSenderEmail = senderEmail;
LPTSTR szAddrType = (TCHAR*)"SMTP";
if(m_strSenderName.GetLength() && m_strSenderEmail.GetLength()) {
SetPropertyString(PR_SENDER_NAME, senderName);
SetPropertyString(PR_SENDER_EMAIL_ADDRESS, senderEmail);
#ifndef _WIN32_WCE
LPADRBOOK pAddressBook;
if(m_pMAPI->GetSession()->OpenAddressBook(0, NULL, AB_NO_DIALOG, &pAddressBook) == S_OK) {
SPropValue prop;
if(pAddressBook->CreateOneOff((LPTSTR)(senderName.Begin()), szAddrType,
(LPTSTR)(senderEmail.Begin()), 0, &prop.Value.bin.cb,
(LPENTRYID*)&prop.Value.bin.lpb) == S_OK) {
prop.ulPropTag=PR_SENT_REPRESENTING_ENTRYID;
Message()->SetProps(1, &prop, NULL);
SetPropertyString(PR_SENT_REPRESENTING_NAME, senderName);
SetPropertyString(PR_SENT_REPRESENTING_EMAIL_ADDRESS, senderEmail);
SetPropertyString(PR_SENT_REPRESENTING_ADDRTYPE, szAddrType);
}
}
RELEASE(pAddressBook);
#endif
}
}
bool MAPIMessage::SetReceivedTime(const Time &tm) {
SYSTEMTIME tmReceived;
MAPIEx::SetSystemTime(tmReceived, tm);
SPropValue prop;
prop.ulPropTag = PR_MESSAGE_DELIVERY_TIME;
#ifndef _WIN32_WCE
// if(bLocalTime) TzSpecificLocalTimeToSystemTime(NULL, &tmReceived, &tmReceived);
#endif
SystemTimeToFileTime(&tmReceived, &prop.Value.ft);
return (Message() && Message()->SetProps(1, &prop, NULL) == S_OK);
}
bool MAPIMessage::SetSubmitTime(const Time &tm) {
SYSTEMTIME tmSubmit;
MAPIEx::SetSystemTime(tmSubmit, tm);
SPropValue prop;
prop.ulPropTag = PR_CLIENT_SUBMIT_TIME;
#ifndef _WIN32_WCE
// if(bLocalTime) TzSpecificLocalTimeToSystemTime(NULL, &tmSubmit, &tmSubmit);
#endif
SystemTimeToFileTime(&tmSubmit, &prop.Value.ft);
return (Message() && Message()->SetProps(1, &prop, NULL) == S_OK);
}
// request a Read Receipt sent to szReceiverEmail
bool MAPIMessage::SetReadReceipt(bool bSet, String szReceiverEmail) {
if(!Message())
return false;
SPropValue prop;
prop.ulPropTag = PR_READ_RECEIPT_REQUESTED;
prop.Value.b = (unsigned short)bSet;
if(Message()->SetProps(1, &prop, NULL) != S_OK)
return false;
if(bSet && !IsNull(szReceiverEmail) && szReceiverEmail.GetLength() > 0)
SetPropertyString(PR_READ_RECEIPT_REQUESTED, szReceiverEmail);
return true;
}
bool MAPIMessage::SetDeliveryReceipt(bool bSet) {
if(!Message())
return false;
SPropValue prop;
prop.ulPropTag = PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED;
prop.Value.b = (unsigned short)bSet;
return (Message()->SetProps(1, &prop, NULL) != S_OK);
}
// limited compare, compares entry IDs and subject to determine if two emails are equal
bool MAPIMessage::operator==(MAPIMessage& message) {
if(!m_entryID.cb || !message.m_entryID.cb || m_entryID.cb!=message.m_entryID.cb)
return false;
if(memcmp(m_entryID.lpb,message.m_entryID.lpb, m_entryID.cb))
return false;
return (!m_strSubject.Compare(message.m_strSubject));
}
// Novell GroupWise customization by jcadmin
#ifndef GROUPWISE
bool MAPIMessage::MarkAsPrivate() { return false; }
#else
#include GWMAPI.h
//(from Novell Developer Kit)
#define SEND_OPTIONS_MARK_PRIVATE 0x00080000L
void MAPIMessage::MarkAsPrivate() {
SPropValue prop;
prop.ulPropTag = PR_NGW_SEND_OPTIONS;
prop.Value.l = NGW_SEND_OPTIONS_MARK_PRIVATE;
return (Message()->SetProps(1, &prop, NULL) == S_OK);
}
#endif
// In WinCE, use MSGSTATUS_RECTYPE_SMS for an SMS, MSGSTATUS_RECTYPE_SMTP for an email
bool MAPIMessage::SetMessageStatus(int nMessageStatus) {
SPropValue prop;
prop.ulPropTag = PR_MSG_STATUS;
prop.Value.ul = nMessageStatus;
return (Message()->SetProps(1, &prop, NULL) == S_OK);
}
// Shows the default MAPI form for IMessage, returns false on failure, IDOK on success or close existing messages
// and IDCANCEL on close new messages
int MAPIMessage::ShowForm(MAPIEx* pMAPI, MAPIFolder &folder) {
//MAPIFolder* pFolder=pMAPI->GetFolder();
IMAPISession* pSession = pMAPI->GetSession();
ULONG ulMessageToken;
if(folder.IsOpened() && pSession && pSession->PrepareForm(NULL,Message(), &ulMessageToken) == S_OK) {
ULONG ulMessageStatus=GetPropertyValue(PR_MSG_STATUS, 0);
ULONG ulMessageFlags=GetMessageFlags();
ULONG ulAccess=GetPropertyValue(PR_ACCESS, 0);
LPSPropValue pProp;
if(GetProperty(PR_MESSAGE_CLASS, pProp) == S_OK) {
char* szMessageClass = pProp->Value.LPSZ;
HRESULT hr = pSession->ShowForm(0, pMAPI->GetMessageStore(), folder.Folder(),
NULL, ulMessageToken, NULL, 0, ulMessageStatus,ulMessageFlags,
ulAccess, szMessageClass);
MAPIFreeBuffer(pProp);
if(hr == S_OK)
return IDOK;
if(hr == MAPI_E_USER_CANCEL)
return IDCANCEL;
}
}
return false;
}
bool MAPIMessage::Send() {
if(Message()) {
HRESULT ret = Message()->SubmitMessage(0);
if (ret == S_OK) {
Close();
return true;
} else
return false;
}
return false;
}
bool MAPIMessage::SaveToFile(const String &fileName) {
if (!RealizePath(fileName))
return false;
#ifdef _WIN32_WCE
return false;
#else
LPSTORAGE pStorage;
DWORD dwFlags = STGM_READWRITE | STGM_TRANSACTED | STGM_CREATE;
if(StgCreateDocfile(fileName.ToWString(), dwFlags, 0, &pStorage) != S_OK)
return false;
LPMSGSESS pMsgSession;
LPMALLOC pMalloc = MAPIGetDefaultMalloc();
if(OpenIMsgSession(pMalloc, 0, &pMsgSession) == S_OK) {
LPMESSAGE pIMsg;
if(OpenIMsgOnIStg(pMsgSession, MAPIAllocateBuffer, MAPIAllocateMore, MAPIFreeBuffer,
pMalloc, NULL, pStorage, NULL, 0, 0, &pIMsg) == S_OK) {
// client must support CLSID_MailMessage as the compound document
if(WriteClassStg(pStorage, CLSID_MailMessage) == S_OK) {
// exclude these properties from the copy operation to speed things up
SizedSPropTagArray (7, excludeTags);
excludeTags.cValues = 7;
excludeTags.aulPropTag[0] = PR_ACCESS;
excludeTags.aulPropTag[1] = PR_BODY;
excludeTags.aulPropTag[2] = PR_RTF_SYNC_BODY_COUNT;
excludeTags.aulPropTag[3] = PR_RTF_SYNC_BODY_CRC;
excludeTags.aulPropTag[4] = PR_RTF_SYNC_BODY_TAG;
excludeTags.aulPropTag[5] = PR_RTF_SYNC_PREFIX_COUNT;
excludeTags.aulPropTag[6] = PR_RTF_SYNC_TRAILING_COUNT;
if(Message()->CopyTo(0, NULL, (LPSPropTagArray)&excludeTags, 0, NULL,
(LPIID)&IID_IMessage, pIMsg, 0, NULL ) == S_OK) {
pIMsg->SaveChanges(KEEP_OPEN_READWRITE);
pStorage->Commit(STGC_DEFAULT);
}
}
RELEASE(pIMsg);
}
CloseIMsgSession(pMsgSession);
}
RELEASE(pStorage);
return true;
#endif
}
#endif