winamp/Src/Plugins/General/gen_crasher/feedback/email/SendEmail.cpp

364 lines
9.9 KiB
C++

// SendEmail.cpp Version 1.0
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// This software is released into the public domain.
// You are free to use it in any way you like, except
// that you may not sell this source code.
//
// This software is provided "as is" with no expressed
// or implied warranty. I accept no liability for any
// damage or loss of business that this software may cause.
//
///////////////////////////////////////////////////////////////////////////////
// Notes on compiling: this does not use MFC. Set precompiled header
// option to "Not using precompiled headers".
//
// This code assumes that a default mail client has been set up.
#include ".\sendemail.h"
#include <crtdbg.h>
#include <io.h>
#pragma warning(disable: 4228)
#include <mapi.h>
#pragma warning(default: 4228)
#pragma warning(disable:4127) // for _ASSERTE
#ifndef _countof
#define _countof(array) (sizeof(array)/sizeof(array[0]))
#endif
BOOL SendEmail(HWND hWnd, // parent window, must not be NULL
LPCTSTR lpszTo, // must NOT be NULL or empty
LPCTSTR lpszToName, // may be NULL
LPCTSTR lpszSubject, // may be NULL
LPCTSTR lpszMessage, // may be NULL
LPCTSTR lpszAttachment) // may be NULL
{
_ASSERTE(lpszTo && lpszTo[0] != _T('\0'));
if (lpszTo == NULL || lpszTo[0] == _T('\0'))
return FALSE;
// ===== LOAD MAPI DLL =====
HMODULE hMapi = ::LoadLibraryA("MAPI32.DLL");
_ASSERTE(hMapi);
if (hMapi == NULL)
{
::MessageBox(NULL,
_T("Failed to load MAPI32.DLL."),
_T("CrashRep"),
MB_OK|MB_ICONSTOP);
return FALSE;
}
// get proc address for MAPISendMail
ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG);
(FARPROC&)lpfnSendMail = GetProcAddress(hMapi, "MAPISendMail");
_ASSERTE(lpfnSendMail);
if (lpfnSendMail == NULL)
{
::MessageBox(NULL,
_T("Invalid MAPI32.DLL, cannot find MAPISendMail."),
_T("CrashRep"),
MB_OK|MB_ICONSTOP);
::FreeLibrary(hMapi);
return FALSE;
}
// ===== SET UP MAPI STRUCTS =====
// ===== file description (for the attachment) =====
MapiFileDesc fileDesc;
memset(&fileDesc, 0, sizeof(fileDesc));
// ----- attachment path
TCHAR szTempName[_MAX_PATH*2];
memset(szTempName, 0, sizeof(szTempName));
if (lpszAttachment && lpszAttachment[0] != _T('\0'))
lstrcpyn(szTempName, lpszAttachment, _countof(szTempName)-2);
#ifdef _UNICODE
char szTempNameA[_MAX_PATH*2];
memset(szTempNameA, 0, sizeof(szTempNameA));
_wcstombsz(szTempNameA, szTempName, _countof(szTempNameA)-2);
#endif
// ----- attachment title
TCHAR szTitle[_MAX_PATH*2];
memset(szTitle, 0, sizeof(szTitle));
if (lpszAttachment && lpszAttachment[0] != _T('\0'))
lstrcpyn(szTitle, GetFilePart(lpszAttachment), _countof(szTitle)-2);
#ifdef _UNICODE
char szTitleA[_MAX_PATH*2];
memset(szTitleA, 0, sizeof(szTitleA));
_wcstombsz(szTitleA, szTitle, _countof(szTitleA)-2);
#endif
fileDesc.nPosition = (ULONG)-1;
#ifdef _UNICODE
fileDesc.lpszPathName = szTempNameA;
fileDesc.lpszFileName = szTitleA;
#else
fileDesc.lpszPathName = szTempName;
fileDesc.lpszFileName = szTitle;
#endif
// ===== recipient =====
MapiRecipDesc recip;
memset(&recip, 0, sizeof(recip));
// ----- name
TCHAR szRecipName[_MAX_PATH*2];
memset(szRecipName, 0, sizeof(szRecipName));
if (lpszToName && lpszToName[0] != _T('\0'))
lstrcpyn(szRecipName, lpszToName, _countof(szRecipName)-2);
#ifdef _UNICODE
char szRecipNameA[_MAX_PATH*2];
memset(szRecipNameA, 0, sizeof(szRecipNameA));
_wcstombsz(szRecipNameA, szRecipName, _countof(szRecipNameA)-2);
#endif
if (lpszToName && lpszToName[0] != _T('\0'))
{
#ifdef _UNICODE
recip.lpszName = szRecipNameA;
#else
recip.lpszName = szRecipName;
#endif
}
// ----- address
TCHAR szAddress[_MAX_PATH*2];
memset(szAddress, 0, sizeof(szAddress));
lstrcpyn(szAddress, lpszTo, _countof(szAddress)-2);
#ifdef _UNICODE
char szAddressA[_MAX_PATH*2];
memset(szAddressA, 0, sizeof(szAddressA));
_wcstombsz(szAddressA, szAddress, _countof(szAddressA)-2);
#endif
#ifdef _UNICODE
recip.lpszAddress = szAddressA;
#else
recip.lpszAddress = szAddress;
#endif
recip.ulRecipClass = MAPI_TO;
// ===== message =====
MapiMessage message;
memset(&message, 0, sizeof(message));
// ----- recipient
message.nRecipCount = 1;
message.lpRecips = &recip;
// ----- attachment
if (lpszAttachment && lpszAttachment[0] != _T('\0'))
{
message.nFileCount = 1;
message.lpFiles = &fileDesc;
}
// ----- subject
TCHAR szSubject[_MAX_PATH*2];
memset(szSubject, 0, sizeof(szSubject));
if (lpszSubject && lpszSubject[0] != _T('\0'))
lstrcpyn(szSubject, lpszSubject, _countof(szSubject)-2);
#ifdef _UNICODE
char szSubjectA[_MAX_PATH*2];
memset(szSubjectA, 0, sizeof(szSubjectA));
_wcstombsz(szSubjectA, szSubject, _countof(szSubjectA)-2);
#endif
if (lpszSubject && lpszSubject[0] != _T('\0'))
{
#ifdef _UNICODE
message.lpszSubject = szSubjectA;
#else
message.lpszSubject = szSubject;
#endif
}
// ----- message
// message may be large, so allocate buffer
TCHAR *pszMessage = NULL;
int nMessageSize = 0;
if (lpszMessage)
{
nMessageSize = lstrlen(lpszMessage);
if (nMessageSize > 0)
{
pszMessage = new TCHAR [nMessageSize + 10];
_ASSERTE(pszMessage);
memset(pszMessage, 0, nMessageSize + 10);
lstrcpy(pszMessage, lpszMessage);
}
}
char *pszMessageA = NULL;
#ifdef _UNICODE
if (nMessageSize > 0)
{
pszMessageA = new char [nMessageSize + 10];
_ASSERTE(pszMessageA);
memset(pszMessageA, 0, nMessageSize + 10);
}
_wcstombsz(pszMessageA, pszMessage, nMessageSize+2);
#endif
if (nMessageSize > 0)
{
#ifdef _UNICODE
message.lpszNoteText = pszMessageA;
#else
message.lpszNoteText = pszMessage;
#endif
}
// ===== SETUP FINISHED, READY TO SEND =====
// some extra precautions are required to use MAPISendMail as it
// tends to enable the parent window in between dialogs (after
// the login dialog, but before the send note dialog).
::SetCapture(hWnd);
::SetFocus(NULL);
::EnableWindow(hWnd, FALSE);
ULONG nError = lpfnSendMail(0,
(LPARAM)hWnd,
&message,
MAPI_LOGON_UI | MAPI_DIALOG,
0);
#ifdef _DEBUG
TCHAR *cp = NULL;
switch (nError)
{
case SUCCESS_SUCCESS: cp = _T("SUCCESS_SUCCESS"); break;
case MAPI_E_USER_ABORT: cp = _T("MAPI_E_USER_ABORT"); break;
case MAPI_E_FAILURE: cp = _T("MAPI_E_FAILURE"); break;
case MAPI_E_LOGON_FAILURE: cp = _T("MAPI_E_LOGON_FAILURE"); break;
case MAPI_E_DISK_FULL: cp = _T("MAPI_E_DISK_FULL"); break;
case MAPI_E_INSUFFICIENT_MEMORY: cp = _T("MAPI_E_INSUFFICIENT_MEMORY"); break;
case MAPI_E_ACCESS_DENIED: cp = _T("MAPI_E_ACCESS_DENIED"); break;
case MAPI_E_TOO_MANY_SESSIONS: cp = _T("MAPI_E_TOO_MANY_SESSIONS"); break;
case MAPI_E_TOO_MANY_FILES: cp = _T("MAPI_E_TOO_MANY_FILES"); break;
case MAPI_E_TOO_MANY_RECIPIENTS: cp = _T("MAPI_E_TOO_MANY_RECIPIENTS"); break;
case MAPI_E_ATTACHMENT_NOT_FOUND: cp = _T("MAPI_E_ATTACHMENT_NOT_FOUND"); break;
case MAPI_E_ATTACHMENT_OPEN_FAILURE: cp = _T("MAPI_E_ATTACHMENT_OPEN_FAILURE"); break;
case MAPI_E_ATTACHMENT_WRITE_FAILURE: cp = _T("MAPI_E_ATTACHMENT_WRITE_FAILURE"); break;
case MAPI_E_UNKNOWN_RECIPIENT: cp = _T("MAPI_E_UNKNOWN_RECIPIENT"); break;
case MAPI_E_BAD_RECIPTYPE: cp = _T("MAPI_E_BAD_RECIPTYPE"); break;
case MAPI_E_NO_MESSAGES: cp = _T("MAPI_E_NO_MESSAGES"); break;
case MAPI_E_INVALID_MESSAGE: cp = _T("MAPI_E_INVALID_MESSAGE"); break;
case MAPI_E_TEXT_TOO_LARGE: cp = _T("MAPI_E_TEXT_TOO_LARGE"); break;
case MAPI_E_INVALID_SESSION: cp = _T("MAPI_E_INVALID_SESSION"); break;
case MAPI_E_TYPE_NOT_SUPPORTED: cp = _T("MAPI_E_TYPE_NOT_SUPPORTED"); break;
case MAPI_E_AMBIGUOUS_RECIPIENT: cp = _T("MAPI_E_AMBIGUOUS_RECIPIENT"); break;
case MAPI_E_MESSAGE_IN_USE: cp = _T("MAPI_E_MESSAGE_IN_USE"); break;
case MAPI_E_NETWORK_FAILURE: cp = _T("MAPI_E_NETWORK_FAILURE"); break;
case MAPI_E_INVALID_EDITFIELDS: cp = _T("MAPI_E_INVALID_EDITFIELDS"); break;
case MAPI_E_INVALID_RECIPS: cp = _T("MAPI_E_INVALID_RECIPS"); break;
case MAPI_E_NOT_SUPPORTED: cp = _T("MAPI_E_NOT_SUPPORTED"); break;
default: cp = _T("unknown error"); break;
}
if (nError == SUCCESS_SUCCESS)
{
OutputDebugString(_T("MAPISendMail ok\r\n"));
}
else
{
OutputDebugString(L"ERROR - MAPISendMail failed: ");
OutputDebugString(cp);
OutputDebugString(L"\r\n");
}
#endif // _DEBUG
// ===== SEND COMPLETE, CLEAN UP =====
// after returning from the MAPISendMail call, the window must be
// re-enabled and focus returned to the frame to undo the workaround
// done before the MAPI call.
::ReleaseCapture();
::EnableWindow(hWnd, TRUE);
::SetActiveWindow(NULL);
::SetActiveWindow(hWnd);
::SetFocus(hWnd);
if (pszMessage)
delete [] pszMessage;
pszMessage = NULL;
if (pszMessageA)
delete [] pszMessageA;
pszMessageA = NULL;
if (hMapi)
::FreeLibrary(hMapi);
hMapi = NULL;
BOOL bRet = TRUE;
if (nError != SUCCESS_SUCCESS) // &&
//nError != MAPI_USER_ABORT &&
//nError != MAPI_E_LOGIN_FAILURE)
{
bRet = FALSE;
}
return bRet;
}
const wchar_t* GetFilePart(LPCWSTR lpszFile)
{
const wchar_t *result = wcsrchr(lpszFile, _T('\\'));
if (result)
result++;
else
result = (wchar_t *) lpszFile;
return result;
}
int xwcstombsz(char* mbstr, const wchar_t* wcstr, size_t count)
{
if (count == 0 && mbstr != NULL)
return 0;
int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1,
mbstr, (int)count, NULL, NULL);
_ASSERTE(mbstr == NULL || result <= (int)count);
if (result > 0)
mbstr[result-1] = 0;
return result;
}
int xmbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count)
{
if (count == 0 && wcstr != NULL)
return 0;
int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1,
wcstr, (int)count);
_ASSERTE(wcstr == NULL || result <= (int)count);
if (result > 0)
wcstr[result-1] = 0;
return result;
}