server-re/third-party/BugTrap-1.3-57bd515/source/CMapi.cpp
2026-10-14 15:54:34 -04:00

538 lines
16 KiB
C++

/*
* This is a part of the BugTrap package.
* Copyright (c) 1999 by PJ Naughter.
* All rights reserved.
*
* Description: Defines the wrapper class for sending an email using simple MAPI
* Updated by: Maksim Pyatkovskiy.
* Note: Based on code developed by PJ Naughter.
* Downloaded from: http://www.codeproject.com/internet/cmapi.asp
*
* This source code is only intended as a supplement to the
* BugTrap package reference and related electronic documentation
* provided with the product. See these sources for detailed
* information regarding the BugTrap package.
*/
#include "StdAfx.h"
#include "CMapi.h"
#include "BugTrapUtils.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CMapiSession::CMapiSession(void)
{
ZeroMemory(this, sizeof(*this));
Initialise();
}
CMapiSession::~CMapiSession(void)
{
// Logoff if logged on
Logoff();
// Unload the MAPI dll
Deinitialise();
}
void CMapiSession::Initialise(void)
{
// First make sure the "WIN.INI" entry for MAPI is present as well
// as the MAPI32 dll being present on the system
if (GetProfileInt(_T("MAIL"), _T("MAPI"), 0) != 0)
{
// Load up the MAPI dll and get the function pointers we are interested in
m_hMapi = LoadLibrary(_T("MAPI32.DLL"));
if (m_hMapi)
{
m_pfnMAPILogon = (LPMAPILOGON) GetProcAddress(m_hMapi, "MAPILogon");
m_pfnMAPILogoff = (LPMAPILOGOFF) GetProcAddress(m_hMapi, "MAPILogoff");
m_pfnMAPISendMail = (LPMAPISENDMAIL) GetProcAddress(m_hMapi, "MAPISendMail");
m_pfnMAPIResolveName = (LPMAPIRESOLVENAME) GetProcAddress(m_hMapi, "MAPIResolveName");
m_pfnMAPIFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress(m_hMapi, "MAPIFreeBuffer");
// If any of the functions are not installed then fail the load
if (m_pfnMAPILogon == NULL ||
m_pfnMAPILogoff == NULL ||
m_pfnMAPISendMail == NULL ||
m_pfnMAPIResolveName == NULL ||
m_pfnMAPIFreeBuffer == NULL)
Deinitialise();
}
}
}
void CMapiSession::Deinitialise(void)
{
if (m_hMapi)
{
// Unload the MAPI dll and reset the function pointers to NULL
FreeLibrary(m_hMapi);
ZeroMemory(this, sizeof(*this));
}
}
/**
* @return true if operation has been completed successfully.
*/
BOOL CMapiSession::Logon(void)
{
if (! MapiInstalled())
return FALSE;
// Just in case we are already logged in
Logoff();
// First try to acquire a new MAPI session using the supplied settings using the MAPILogon() function
m_ulLastError = m_pfnMAPILogon(0, NULL, NULL, 0, 0, &m_hSession);
_ASSERTE(m_ulLastError == SUCCESS_SUCCESS);
return (m_ulLastError == SUCCESS_SUCCESS);
}
/**
* @param pszProfileName - profile name.
* @param pszPassword - profile password.
* @param bNewSession - pass true to open new session instead of attempting to re-use existing shared session.
* @return true if operation has been completed successfully.
*/
BOOL CMapiSession::Logon(PCTSTR pszProfileName, PCTSTR pszPassword, BOOL bNewSession)
{
if (! MapiInstalled() || pszProfileName == NULL || *pszProfileName == _T('\0'))
return FALSE;
// Just in case we are already logged in
Logoff();
// Initialize flags parameter used in the MAPILogon() call
FLAGS flags = 0;
if (bNewSession)
flags |= MAPI_NEW_SESSION;
// Get the ASCII versions of the profile name and password
PCSTR pszProfileName2, pszPassword2;
#ifdef _UNICODE
CHAR szProfileNameA[MAX_PATH], szPasswordA[MAX_PATH];
if (pszProfileName)
WideCharToMultiByte(CP_ACP, 0, pszProfileName, -1, szProfileNameA, countof(szProfileNameA), NULL, NULL);
else
*szProfileNameA = '\0';
if (pszPassword)
WideCharToMultiByte(CP_ACP, 0, pszPassword, -1, szPasswordA, countof(szPasswordA), NULL, NULL);
else
*szPasswordA = '\0';
pszProfileName2 = szProfileNameA;
pszPassword2 = szPasswordA;
#else
pszProfileName2 = pszProfileName;
pszPassword2 = pszPassword;
#endif
// First try to acquire a new MAPI session using the supplied settings using the MAPILogon() function
m_ulLastError = m_pfnMAPILogon(0, (PSTR)pszProfileName2, (PSTR)pszPassword2, flags, 0, &m_hSession);
_ASSERTE(m_ulLastError == SUCCESS_SUCCESS);
return (m_ulLastError == SUCCESS_SUCCESS);
}
/**
* @param hwndParent - parent window if you want to show the UI.
* @param bNewSession - pass true to open new session instead of attempting to re-use existing shared session.
* @return true if operation has been completed successfully.
*/
BOOL CMapiSession::Logon(HWND hwndParent, BOOL bNewSession)
{
if (! MapiInstalled())
return FALSE;
// Just in case we are already logged in
Logoff();
// Initialize flags parameter used in the MAPILogon() call
FLAGS flags = MAPI_LOGON_UI;
if (bNewSession)
flags |= MAPI_NEW_SESSION;
// First try to acquire a new MAPI session using the supplied settings using the MAPILogon() function
m_ulLastError = m_pfnMAPILogon((ULONG)hwndParent, NULL, NULL, flags, 0, &m_hSession);
_ASSERTE(m_ulLastError == SUCCESS_SUCCESS);
return (m_ulLastError == SUCCESS_SUCCESS);
}
/**
* @return true if operation has been completed successfully.
*/
BOOL CMapiSession::Logoff(void)
{
if (! MapiInstalled())
return FALSE;
if (m_hSession)
{
// Call the MAPILogoff() function
m_ulLastError = m_pfnMAPILogoff(m_hSession, 0, 0, 0);
_ASSERTE(m_ulLastError == SUCCESS_SUCCESS);
m_hSession = NULL;
}
return TRUE;
}
/**
* @param strName - resolved name.
* @param lpRecip - recipient information.
* @return true if operation has been complete successfully.
*/
BOOL CMapiSession::Resolve(const CStrHolder& strName, lpMapiRecipDesc& lpRecip)
{
if (! MapiInstalled() || ! LoggedOn() || strName.IsEmpty())
return FALSE;
#ifdef _UNICODE
CHAR szNameA[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, strName, -1, szNameA, countof(szNameA), NULL, NULL);
PCSTR pszName = szNameA;
#else
PCSTR pszName = strName;
#endif
m_ulLastError = m_pfnMAPIResolveName(m_hSession, 0, (PSTR)pszName, 0, 0, &lpRecip);
_ASSERTE(m_ulLastError == SUCCESS_SUCCESS);
return (m_ulLastError == SUCCESS_SUCCESS);
}
/**
* @param pBuffer - pointer to de-allocated buffer.
* @return true if operation has been complete successfully.
*/
BOOL CMapiSession::FreeBuffer(PVOID pBuffer)
{
if (! MapiInstalled())
return FALSE;
if (pBuffer == NULL)
return TRUE;
m_ulLastError = m_pfnMAPIFreeBuffer(pBuffer);
_ASSERTE(m_ulLastError == SUCCESS_SUCCESS);
return (m_ulLastError == SUCCESS_SUCCESS);
}
/**
* @param ulRecipClass - kind of recipient.
* @param rRecipDesc - recipient information.
* @param strName - recipient name.
*/
void CMapiSession::InitRecipient(ULONG ulRecipClass, MapiRecipDesc& rRecipDesc, const CStrHolder& strName)
{
PCTSTR pszName = strName;
// Set recipient type
rRecipDesc.ulRecipClass = ulRecipClass;
PCTSTR pszBracket1, pszBracket2;
// John Smith <jsmith@aol.com>
if ((pszBracket1 = _tcschr(pszName, _T('<'))) != NULL &&
(pszBracket2 = _tcschr(pszBracket1 + 1, _T('>'))) != NULL)
{
// Copy name
size_t nLength = pszBracket1 - pszName;
#ifdef _UNICODE
int nLengthA = WideCharToMultiByte(CP_ACP, 0, pszName, (int)nLength, NULL, 0, NULL, NULL);
rRecipDesc.lpszName = new CHAR[nLengthA + 1];
#else
rRecipDesc.lpszName = new CHAR[nLength + 1];
#endif
if (rRecipDesc.lpszName)
{
#ifdef _UNICODE
WideCharToMultiByte(CP_ACP, 0, pszName, (int)nLength, rRecipDesc.lpszName, nLengthA, NULL, NULL);
rRecipDesc.lpszName[nLengthA] = '\0';
#else
strcpy_s(rRecipDesc.lpszName, nLength + 1, pszName);
#endif
TrimSpacesA(rRecipDesc.lpszName);
}
// Copy address
PCTSTR pszAddress = pszBracket1 + 1;
nLength = pszBracket2 - pszAddress;
#ifdef _UNICODE
nLengthA = WideCharToMultiByte(CP_ACP, 0, pszAddress, (int)nLength, NULL, 0, NULL, NULL);
rRecipDesc.lpszAddress = new CHAR[nLengthA + 1];
#else
rRecipDesc.lpszAddress = new CHAR[nLength + 1];
#endif
if (rRecipDesc.lpszAddress)
{
#ifdef _UNICODE
WideCharToMultiByte(CP_ACP, 0, pszAddress, (int)nLength, rRecipDesc.lpszAddress, nLengthA, NULL, NULL);
rRecipDesc.lpszAddress[nLengthA] = '\0';
#else
strcpy_s(rRecipDesc.lpszAddress, nLength + 1, pszAddress);
#endif
TrimSpacesA(rRecipDesc.lpszAddress);
}
}
else
{
size_t nSize;
// Try to resolve the name
lpMapiRecipDesc lpTempRecip = NULL;
if (_tcschr(pszName, _T('@')) == NULL &&
Resolve(strName, lpTempRecip))
{
// Resolve worked, put the resolved name/address back into the array
if (lpTempRecip->lpszName)
{
nSize = strlen(lpTempRecip->lpszName) + 1;
rRecipDesc.lpszName = new CHAR[nSize];
if (rRecipDesc.lpszName)
strcpy_s(rRecipDesc.lpszName, nSize, lpTempRecip->lpszName);
}
if (lpTempRecip->lpszAddress)
{
nSize = strlen(lpTempRecip->lpszAddress) + 1;
rRecipDesc.lpszAddress = new CHAR[nSize];
if (rRecipDesc.lpszAddress)
strcpy_s(rRecipDesc.lpszAddress, nSize, lpTempRecip->lpszAddress);
}
// Don't forget to free up the memory MAPI allocated for us
FreeBuffer(lpTempRecip);
}
else
{
#ifdef _UNICODE
nSize = WideCharToMultiByte(CP_ACP, 0, pszName, -1, NULL, 0, NULL, NULL);
#else
nSize = strName.GetLength() + 1;
#endif
rRecipDesc.lpszName = new CHAR[nSize];
if (rRecipDesc.lpszName)
{
#ifdef _UNICODE
WideCharToMultiByte(CP_ACP, 0, pszName, -1, rRecipDesc.lpszName, (int)nSize, NULL, NULL);
#else
strcpy_s(rRecipDesc.lpszName, nSize, pszName);
#endif
}
}
}
}
/**
* @param ulRecipClass - kind of recipients.
* @param lpRecips - array of recipient descriptors.
* @param nRecipIndex - current position of initialized recipient descriptor in the array.
* @param arrRecipients - recipient names.
*/
void CMapiSession::InitRecipients(ULONG ulRecipClass, lpMapiRecipDesc lpRecips, size_t& nRecipIndex, const CArray<CStrHolder>& arrRecipients)
{
size_t nNumRecipients = arrRecipients.GetCount();
for (size_t i = 0; i < nNumRecipients; ++i, ++nRecipIndex)
InitRecipient(ulRecipClass, lpRecips[nRecipIndex + i], arrRecipients[i]);
}
/**
* @param rMessage - message object.
* @param bShowMessageEditor - true if you wan to show message editor.
* @param hwndParent - parent window for the UI.
* @param bNewSession - pass true to open new session instead of attempting to re-use existing shared session.
* @return true if operation has been completed successfully.
*/
BOOL CMapiSession::Send(const CMapiMessage& rMessage, BOOL bShowMessageEditor, HWND hwndParent, BOOL bNewSession)
{
if (! MapiInstalled() || (bNewSession ? LoggedOn() : ! LoggedOn()))
return FALSE;
const CArray<CStrHolder>& arrAttachments = rMessage.GetAttachments();
size_t nNumAttachments = arrAttachments.GetCount();
const CArray<CStrHolder>& arrAttachmentTitles = rMessage.GetAttachmentTitles();
size_t nNumAttachmentTitles = arrAttachmentTitles.GetCount();
if (nNumAttachments != nNumAttachmentTitles && nNumAttachmentTitles != 0)
return FALSE;
// Create the MapiMessage structure to match the message parameter send into us
const CArray<CStrHolder>& arrTo = rMessage.GetTo();
const CArray<CStrHolder>& arrCC = rMessage.GetCC();
const CArray<CStrHolder>& arrBCC = rMessage.GetBCC();
MapiMessage mapiMessage;
ZeroMemory(&mapiMessage, sizeof(mapiMessage));
size_t nRecipCount = arrTo.GetCount() + arrCC.GetCount() + arrBCC.GetCount();
size_t nFileIndex, nRecipIndex;
if (nRecipCount > 0)
{
mapiMessage.nRecipCount = (ULONG)nRecipCount;
// Allocate the recipients array
mapiMessage.lpRecips = new MapiRecipDesc[nRecipCount];
if (mapiMessage.lpRecips)
{
ZeroMemory(mapiMessage.lpRecips, sizeof(*mapiMessage.lpRecips) * nRecipCount);
nRecipIndex = 0;
// Setup the "To" recipients
InitRecipients(MAPI_TO, mapiMessage.lpRecips, nRecipIndex, arrTo);
// Setup the "CC" recipients
InitRecipients(MAPI_CC, mapiMessage.lpRecips, nRecipIndex, arrCC);
// Setup the "BCC" recipients
InitRecipients(MAPI_BCC, mapiMessage.lpRecips, nRecipIndex, arrBCC);
}
}
// Setup the sender
const CStrHolder& strFrom = rMessage.GetFrom();
if (! strFrom.IsEmpty())
{
MapiRecipDesc recipOrigin;
ZeroMemory(&recipOrigin, sizeof(recipOrigin));
InitRecipient(MAPI_ORIG, recipOrigin, strFrom);
mapiMessage.lpOriginator = &recipOrigin;
}
// Setup the attachments
if (nNumAttachments)
{
mapiMessage.nFileCount = (ULONG)nNumAttachments;
mapiMessage.lpFiles = new MapiFileDesc[nNumAttachments];
if (mapiMessage.lpFiles)
{
ZeroMemory(mapiMessage.lpFiles, sizeof(*mapiMessage.lpFiles) * nNumAttachments);
for (nFileIndex = 0; nFileIndex < nNumAttachments; ++nFileIndex)
{
MapiFileDesc& file = mapiMessage.lpFiles[nFileIndex];
file.nPosition = MAXUINT;
PCTSTR pszFileName = arrAttachments[nFileIndex];
#ifdef _UNICODE
size_t nSize = WideCharToMultiByte(CP_ACP, 0, pszFileName, -1, NULL, 0, NULL, NULL);
#else
size_t nSize = strlen(pszFileName) + 1;
#endif
file.lpszPathName = new CHAR[nSize];
if (file.lpszPathName)
{
#ifdef _UNICODE
WideCharToMultiByte(CP_ACP, 0, pszFileName, -1, file.lpszPathName, (int)nSize, NULL, NULL);
#else
strcpy_s(file.lpszPathName, nSize, pszFileName);
#endif
}
if (nNumAttachmentTitles)
{
PCTSTR pszTitle = arrAttachmentTitles[nFileIndex];
#ifdef _UNICODE
nSize = WideCharToMultiByte(CP_ACP, 0, pszTitle, -1, NULL, 0, NULL, NULL);
#else
nSize = strlen(pszTitle) + 1;
#endif
file.lpszFileName = new CHAR[nSize];
if (file.lpszFileName)
{
#ifdef _UNICODE
WideCharToMultiByte(CP_ACP, 0, pszTitle, -1, file.lpszFileName, (int)nSize, NULL, NULL);
#else
strcpy_s(file.lpszFileName, nSize, pszTitle);
#endif
}
}
else
file.lpszFileName = NULL;
}
}
}
const CStrHolder& strSubject = rMessage.GetSubject();
const CStrHolder& strBody = rMessage.GetBody();
#ifdef _UNICODE
PCWSTR pszSubject = strSubject;
PSTR pszSubjectA;
if (pszSubject)
{
#ifdef _UNICODE
size_t nSubjectSize = WideCharToMultiByte(CP_ACP, 0, pszSubject, -1, NULL, 0, NULL, NULL);
#else
size_t nSubjectSize = strSubject.GetLength() + 1;
#endif
pszSubjectA = new CHAR[nSubjectSize];
if (pszSubjectA)
{
// Perform Unicode to ANSI conversion
WideCharToMultiByte(CP_ACP, 0, pszSubject, -1, pszSubjectA, (int)nSubjectSize, NULL, NULL);
}
}
else
pszSubjectA = NULL;
mapiMessage.lpszSubject = pszSubjectA;
PCWSTR pszBody = strBody;
PSTR pszBodyA;
if (pszBody)
{
#ifdef _UNICODE
size_t nBodySize = WideCharToMultiByte(CP_ACP, 0, pszBody, -1, NULL, 0, NULL, NULL);
#else
size_t nBodySize = strBody.GetLength() + 1;
#endif
pszBodyA = new CHAR[nBodySize];
if (pszBodyA)
{
// Perform Unicode to ANSI conversion
WideCharToMultiByte(CP_ACP, 0, pszBody, -1, pszBodyA, (int)nBodySize, NULL, NULL);
}
}
else
pszBodyA = NULL;
mapiMessage.lpszNoteText = pszBodyA;
#else
mapiMessage.lpszSubject = (PSTR)(PCSTR)strSubject;
mapiMessage.lpszNoteText = (PSTR)(PCSTR)strBody;
#endif
// Initialize flags and UIParam parameters used in the MAPISendMail() call
FLAGS flags = 0;
// Force user to interactively input recipients list and other info.
if (bShowMessageEditor)
{
flags |= MAPI_DIALOG;
if (! m_hSession)
{
flags |= MAPI_LOGON_UI;
if (bNewSession)
flags |= MAPI_NEW_SESSION;
}
}
// Do the actual send using MAPISendMail()
m_ulLastError = m_pfnMAPISendMail(m_hSession, (ULONG)hwndParent, &mapiMessage, flags, 0);
_ASSERTE(m_ulLastError == SUCCESS_SUCCESS);
// Tidy up the attachments
if (nNumAttachments)
{
for (nFileIndex = 0; nFileIndex < nNumAttachments; ++nFileIndex)
{
MapiFileDesc& file = mapiMessage.lpFiles[nFileIndex];
delete[] file.lpszPathName;
delete[] file.lpszFileName;
}
delete [] mapiMessage.lpFiles;
}
// Free up the recipients memory
if (nRecipCount > 0)
{
for (nRecipIndex = 0; nRecipIndex < nRecipCount; ++nRecipIndex)
{
delete[] mapiMessage.lpRecips[nRecipIndex].lpszName;
delete[] mapiMessage.lpRecips[nRecipIndex].lpszAddress;
}
delete [] mapiMessage.lpRecips;
if (mapiMessage.lpOriginator)
{
delete[] mapiMessage.lpOriginator->lpszName;
delete[] mapiMessage.lpOriginator->lpszAddress;
}
}
#ifdef _UNICODE
delete[] pszSubjectA;
delete[] pszBodyA;
#endif
return (m_ulLastError == SUCCESS_SUCCESS);
}