diff options
author | RĂ¼diger Timm <rt@openoffice.org> | 2004-06-17 14:43:56 +0000 |
---|---|---|
committer | RĂ¼diger Timm <rt@openoffice.org> | 2004-06-17 14:43:56 +0000 |
commit | 9c80ffd6ddd523a444ff3e1a51028e2e765b66de (patch) | |
tree | 3d522c5d1e91cbf039720b1ab1e37b39be6eeaee /shell/source/win32/simplemail | |
parent | acf4145fc4a2e49a6de6067dec633b01d246513c (diff) |
INTEGRATION: CWS defaultmailer (1.9.36); FILE MERGED
2004/06/07 13:51:40 tra 1.9.36.3: #i29558#now evaluating registry key for alternative senddoc executable as specified
2004/06/07 12:05:50 tra 1.9.36.2: #i29558#using osl_Process_DETACHED in order to avoid a console popup
2004/06/04 15:09:42 tra 1.9.36.1: #i29558#refactoring of simple mail service, MAPI stuff now called in an own executable
Diffstat (limited to 'shell/source/win32/simplemail')
-rw-r--r-- | shell/source/win32/simplemail/smplmailclient.cxx | 594 |
1 files changed, 209 insertions, 385 deletions
diff --git a/shell/source/win32/simplemail/smplmailclient.cxx b/shell/source/win32/simplemail/smplmailclient.cxx index 71eba297dff4..d09d1e4ad9c0 100644 --- a/shell/source/win32/simplemail/smplmailclient.cxx +++ b/shell/source/win32/simplemail/smplmailclient.cxx @@ -2,9 +2,9 @@ * * $RCSfile: smplmailclient.cxx,v $ * - * $Revision: 1.9 $ + * $Revision: 1.10 $ * - * last change: $Author: rt $ $Date: 2003-10-06 15:44:41 $ + * last change: $Author: rt $ $Date: 2004-06-17 15:43:56 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -59,14 +59,18 @@ * ************************************************************************/ -//------------------------------------------------------------------------ -// includes -//------------------------------------------------------------------------ - #ifndef _OSL_DIAGNOSE_H_ #include <osl/diagnose.h> #endif +#ifndef _OSL_PROCESS_H_ +#include <osl/process.h> +#endif + +#ifndef _OSL_MODULE_HXX_ +#include <osl/module.hxx> +#endif + #ifndef _SMPLMAILCLIENT_HXX_ #include "smplmailclient.hxx" #endif @@ -79,435 +83,255 @@ #include <com/sun/star/system/SimpleMailClientFlags.hpp> #endif -#ifndef _RTL_TENCINFO_H -#include <rtl/tencinfo.h> -#endif - -#ifndef _OSL_THREAD_H_ -#include <osl/thread.h> -#endif - #ifndef _OSL_FILE_HXX_ #include <osl/file.hxx> #endif -#include <process.h> +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mapi.h> -//------------------------------------------------------------------------ -// namespace directives -//------------------------------------------------------------------------ - -using com::sun::star::uno::Reference; -using com::sun::star::uno::Exception; -using com::sun::star::uno::RuntimeException; -using com::sun::star::uno::Sequence; -using com::sun::star::lang::IllegalArgumentException; -using com::sun::star::system::XSimpleMailClient; -using com::sun::star::system::XSimpleMailMessage; -using rtl::OUString; -using rtl::OString; -using osl::Mutex; - -using namespace com::sun::star::system::SimpleMailClientFlags; -using namespace cppu; - -//------------------------------------------------ -// -//------------------------------------------------ - -namespace // private +#include <process.h> +#include <vector> + +using css::uno::Reference; +using css::uno::Exception; +using css::uno::RuntimeException; +using css::uno::Sequence; +using css::lang::IllegalArgumentException; + +using css::system::XSimpleMailClient; +using css::system::XSimpleMailMessage; +using css::system::SimpleMailClientFlags::NO_USER_INTERFACE; +using css::system::SimpleMailClientFlags::NO_LOGON_DIALOG; + +typedef std::vector<rtl::OUString> StringList_t; +typedef StringList_t::const_iterator StringListIterator_t; + +const rtl::OUString TO = rtl::OUString::createFromAscii("--to"); +const rtl::OUString CC = rtl::OUString::createFromAscii("--cc"); +const rtl::OUString BCC = rtl::OUString::createFromAscii("--bcc"); +const rtl::OUString FROM = rtl::OUString::createFromAscii("--from"); +const rtl::OUString SUBJECT = rtl::OUString::createFromAscii("--subject"); +const rtl::OUString BODY = rtl::OUString::createFromAscii("--body"); +const rtl::OUString ATTACH = rtl::OUString::createFromAscii("--attach"); +const rtl::OUString FLAG_MAPI_DIALOG = rtl::OUString::createFromAscii("--mapi-dialog"); +const rtl::OUString FLAG_MAPI_LOGON_UI = rtl::OUString::createFromAscii("--mapi-logon-ui"); + +namespace /* private */ { - const sal_uInt32 LEN_SMTP_PREFIX = 5; // "SMTP:" - - inline - OString getSmtpPrefixedEmailAddress( const OUString& aAddress ) + /** @internal + look if an alternative program is configured + which should be used as senddoc executable */ + rtl::OUString getAlternativeSenddocUrl() { - return OString( "SMTP:" ) + - OString( - aAddress.getStr( ), - aAddress.getLength( ), - osl_getThreadTextEncoding( ) ); + rtl::OUString altSenddocUrl; + HKEY hkey; + LONG lret = RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\OpenOffice.org\\SendAsEMailClient", &hkey); + if (lret == ERROR_SUCCESS) + { + wchar_t buff[MAX_PATH]; + LONG sz = sizeof(buff); + lret = RegQueryValueW(hkey, NULL, buff, &sz); + if (lret == ERROR_SUCCESS) + { + osl::FileBase::getFileURLFromSystemPath(buff, altSenddocUrl); + } + RegCloseKey(hkey); + } + return altSenddocUrl; } - struct MAPISendMailParam - { - CSimpleMapi* pSimpleMapi; - LHANDLE lhSession; - ULONG ulUIParam; - lpMapiMessage lpMessage; - FLAGS flFlags; - }; - -} // end private namespace - -//------------------------------------------------ -// -//------------------------------------------------ - -CSmplMailClient::CSmplMailClient( LHANDLE hMapiSession ) : - m_hMapiSession( hMapiSession ), - m_pSimpleMapi( CSimpleMapi::create( ) ) -{ - OSL_ASSERT( m_hMapiSession ); -} - -//------------------------------------------------ -// -//------------------------------------------------ - -CSmplMailClient::~CSmplMailClient( ) -{ - ULONG ulRet = m_pSimpleMapi->MAPILogoff( m_hMapiSession, 0, 0, 0 ); - OSL_ASSERT( SUCCESS_SUCCESS == ulRet ); -} + /** + Returns the absolute file Url of the senddoc executable. -//------------------------------------------------ -// -//------------------------------------------------ - -Reference< XSimpleMailMessage > SAL_CALL CSmplMailClient::createSimpleMailMessage( ) - throw (::com::sun::star::uno::RuntimeException) -{ - return Reference< XSimpleMailMessage >( new CSmplMailMsg( ) ); -} - -//------------------------------------------------ -// -//------------------------------------------------ - -void SAL_CALL CSmplMailClient::sendSimpleMailMessage( const Reference< XSimpleMailMessage >& xSimpleMailMessage, sal_Int32 aFlag ) - throw (IllegalArgumentException, Exception, RuntimeException) -{ - try + @returns + the absolute file Url of the senddoc executable. In case + of an error an empty string will be returned. + */ + rtl::OUString getSenddocUrl() { - validateParameter( xSimpleMailMessage, aFlag ); + rtl::OUString senddocUrl = getAlternativeSenddocUrl(); - MapiMessage mapiMsg; - FLAGS flFlags; - - initMapiMessage( xSimpleMailMessage, mapiMsg ); - initMapiSendMailFlags( aFlag, flFlags ); - - // fix for #95743 we must create a separate thread because - // again simple mapi works only from within a STA thread :-( - ULONG ulRet = threadExecuteMAPISendMail( - m_pSimpleMapi, - m_hMapiSession, // we use an existing session #93077# - 0, // no parent window - &mapiMsg, // a configured mapi message struct - flFlags ); // reserved - - if ( SUCCESS_SUCCESS != ulRet ) + if (senddocUrl.getLength() == 0) { - throw Exception( - getMapiErrorMsg( ulRet ), - static_cast< XSimpleMailClient* >( this ) ); + rtl::OUString baseUrl; + if (!osl::Module::getUrlFromAddress(getSenddocUrl, baseUrl)) + return rtl::OUString(); + + senddocUrl = baseUrl.copy(0, baseUrl.lastIndexOf('/') + 1); + senddocUrl += rtl::OUString::createFromAscii("senddoc.exe"); } + return senddocUrl; } - catch( RuntimeException& ) - { - OSL_ASSERT( sal_False ); - } -} -//------------------------------------------------ -// -//------------------------------------------------ + /** + Execute Senddoc.exe which a MAPI wrapper. -ULONG SAL_CALL CSmplMailClient::threadExecuteMAPISendMail( CSimpleMapi* pSimpleMapi, LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage, FLAGS flFlags ) -{ - ULONG ulRet = MAPI_E_FAILURE; - unsigned ThreadId; + @param rCommandArgs + [in] the arguments to be passed to Senddoc.exe - MAPISendMailParam param; - - param.pSimpleMapi = pSimpleMapi; - param.lhSession = lhSession; - param.ulUIParam = ulUIParam; - param.lpMessage = lpMessage; - param.flFlags = flFlags; - - HANDLE hThread = reinterpret_cast< HANDLE >( - _beginthreadex( 0, 0, CSmplMailClient::threadProc, ¶m, 0, &ThreadId ) ); - - OSL_ENSURE( hThread, "could not create STA thread" ); - - if ( hThread ) + @returns + <TRUE/> on success. + */ + bool executeSenddoc(const StringList_t& rCommandArgs) { - // stop the calling thread until the sta thread has ended - WaitForSingleObject( hThread, INFINITE ); - GetExitCodeThread( hThread, &ulRet ); - CloseHandle( hThread ); + rtl::OUString senddocUrl = getSenddocUrl(); + if (senddocUrl.getLength() == 0) + return false; + + oslProcess proc; + oslProcessError err = osl_Process_E_Unknown; + + /* for efficiency reasons we are using a 'bad' cast here + as a vector or rtl::OUStrings is nothing else than + an array of pointers to rtl_uString's */ + err = osl_executeProcess( + senddocUrl.pData, + (rtl_uString**)&rCommandArgs[0], + rCommandArgs.size(), + osl_Process_WAIT | osl_Process_DETACHED, + NULL, + NULL, + NULL, + 0, + &proc); + + if (err != osl_Process_E_None) + return false; + + oslProcessInfo procInfo; + procInfo.Size = sizeof(oslProcessInfo); + osl_getProcessInfo(proc, osl_Process_EXITCODE, &procInfo); + osl_freeProcessHandle(proc); + return (procInfo.Code == SUCCESS_SUCCESS); } +} // namespace private - return ulRet; -} - -//------------------------------------------------ -// -//------------------------------------------------ - -unsigned __stdcall CSmplMailClient::threadProc( void* pParam ) +Reference<XSimpleMailMessage> SAL_CALL CSmplMailClient::createSimpleMailMessage() + throw (RuntimeException) { - MAPISendMailParam* param = reinterpret_cast< MAPISendMailParam* >( pParam ); - - CSimpleMapi* pSimpleMapi = param->pSimpleMapi; - - OSL_ENSURE( pSimpleMapi, "invalid thread parameter" ); - - return pSimpleMapi->MAPISendMail( - param->lhSession, // we use an existing session #93077# - param->ulUIParam, // no parent window - param->lpMessage, // a configured mapi message struct - param->flFlags, // some flags - 0 ); // reserved + return Reference<XSimpleMailMessage>(new CSmplMailMsg()); } -//------------------------------------------------ -// -//------------------------------------------------ +/** + Assemble a command line for SendDoc.exe out of the members + of the supplied SimpleMailMessage. -void CSmplMailClient::validateParameter( - const Reference< XSimpleMailMessage >& xSimpleMailMessage, sal_Int32 aFlag ) -{ - // check the flags, the allowed range is 0 - (2^n - 1) - if ( aFlag < 0 || aFlag > 3 ) - throw IllegalArgumentException( - OUString::createFromAscii( "Invalid flag value" ), - static_cast< XSimpleMailClient* >( this ), - 2 ); + @param xSimpleMailMessage + [in] the mail message. - // check if a recipient is specified of the flags NO_USER_INTERFACE is specified - if ( (aFlag & NO_USER_INTERFACE) && !xSimpleMailMessage->getRecipient( ).getLength( ) ) - throw IllegalArgumentException( - OUString::createFromAscii( "No recipient specified" ), - static_cast< XSimpleMailClient* >( this ), - 1 ); -} + @param aFlags + [in] different flags to be used with the simple mail service. -//------------------------------------------------ -// -//------------------------------------------------ + @param rCommandArgs + [in|out] a buffer for the command line arguments. The buffer + is assumed to be empty. -void CSmplMailClient::initMapiMessage( - const Reference< XSimpleMailMessage >& xSimpleMailMessage, MapiMessage& aMapiMessage ) + @throws com::sun::star::lang::IllegalArgumentException + if an invalid file URL has been detected in the attachment list. +*/ +void CSmplMailClient::assembleCommandLine( + const Reference<XSimpleMailMessage>& xSimpleMailMessage, + sal_Int32 aFlag, StringList_t& rCommandArgs) { - ZeroMemory( &aMapiMessage, sizeof( aMapiMessage ) ); + OSL_ENSURE(rCommandArgs.size() == 0, "Provided command argument buffer not empty"); - if ( xSimpleMailMessage.is( ) ) + rtl::OUString to = xSimpleMailMessage->getRecipient(); + if (to.getLength() > 0) { - // unfortunately the simple mapi functions have - // only an ANSI prototype, so we have to convert - // all strings to ascii assuming an us-ascii - // encoding - - // we hand the buffer of this OStrings directly - // to the MapiMessage members but have to - // cast away the constness of the returned buffer - // pointer, we assume the function MAPISendMail - // doesn't alter the strings - - m_Subject = OString( - xSimpleMailMessage->getSubject( ).getStr( ), - xSimpleMailMessage->getSubject( ).getLength( ), - osl_getThreadTextEncoding( ) ); - - aMapiMessage.lpszSubject = const_cast< LPSTR >( m_Subject.getStr( ) ); - - // set the originator information - - if ( xSimpleMailMessage->getOriginator( ).getLength( ) ) - { - ZeroMemory( &m_MsgOriginator, sizeof( m_MsgOriginator ) ); - - m_SmtpAddressOriginator = getSmtpPrefixedEmailAddress( - xSimpleMailMessage->getOriginator( ) ); - - m_MsgOriginator.ulRecipClass = MAPI_ORIG; - m_MsgOriginator.lpszName = ""; - m_MsgOriginator.lpszAddress = - const_cast< LPSTR >( m_SmtpAddressOriginator.getStr( ) ); - - aMapiMessage.lpOriginator = &m_MsgOriginator; - } - - // set the recipient information - - sal_uInt32 nRecips = calcNumRecipients( xSimpleMailMessage ); - if ( nRecips > 0 ) - { - m_RecipientList.realloc( nRecips ); - m_RecipientList.clean( ); - m_RecipsSmtpAddressList.clear( ); - - size_t nPos = 0; - - // init the main recipient - OUString aRecipient = xSimpleMailMessage->getRecipient( ); - if ( aRecipient.getLength( ) ) - { - m_RecipsSmtpAddressList.push_back( - getSmtpPrefixedEmailAddress( aRecipient ) ); - - m_RecipientList[nPos].ulRecipClass = MAPI_TO; - m_RecipientList[nPos].lpszName = - const_cast< LPSTR >( m_RecipsSmtpAddressList.back( ).getStr( ) + LEN_SMTP_PREFIX ); - m_RecipientList[nPos].lpszAddress = - const_cast< LPSTR >( m_RecipsSmtpAddressList.back( ).getStr( ) ); - - nPos++; - } + rCommandArgs.push_back(TO); + rCommandArgs.push_back(to); + } - // add all cc recipients to the list - initRecipientList( - xSimpleMailMessage->getCcRecipient( ), - MAPI_CC, - nPos ); + Sequence<rtl::OUString> ccRecipients = xSimpleMailMessage->getCcRecipient(); + for (int i = 0; i < ccRecipients.getLength(); i++) + { + rCommandArgs.push_back(CC); + rCommandArgs.push_back(ccRecipients[i]); + } - // add all bcc recipients to the list - initRecipientList( - xSimpleMailMessage->getBccRecipient( ), - MAPI_BCC, - nPos ); + Sequence<rtl::OUString> bccRecipients = xSimpleMailMessage->getBccRecipient(); + for (i = 0; i < bccRecipients.getLength(); i++) + { + rCommandArgs.push_back(BCC); + rCommandArgs.push_back(bccRecipients[i]); + } - aMapiMessage.lpRecips = &m_RecipientList; - aMapiMessage.nRecipCount = m_RecipientList.size( ); - } + rtl::OUString from = xSimpleMailMessage->getOriginator(); + if (from.getLength() > 0) + { + rCommandArgs.push_back(FROM); + rCommandArgs.push_back(from); + } - initAttachementList( xSimpleMailMessage ); - aMapiMessage.lpFiles = &m_AttachementList; - aMapiMessage.nFileCount = m_AttachementList.size( ); + rtl::OUString subject = xSimpleMailMessage->getSubject(); + if (subject.getLength() > 0) + { + rCommandArgs.push_back(SUBJECT); + rCommandArgs.push_back(subject); } -} -//------------------------------------------------ -// -//------------------------------------------------ + Sequence<rtl::OUString> attachments = xSimpleMailMessage->getAttachement(); + for (i = 0; i < attachments.getLength(); i++) + { + rtl::OUString sysPath; + osl::FileBase::RC err = osl::FileBase::getSystemPathFromFileURL(attachments[i], sysPath); + if (err != osl::FileBase::E_None) + throw IllegalArgumentException( + rtl::OUString::createFromAscii("Invalid attachment file URL"), + static_cast<XSimpleMailClient*>(this), + 1); -sal_uInt32 CSmplMailClient::calcNumRecipients( - const Reference< XSimpleMailMessage >& xSimpleMailMessage ) -{ - sal_uInt32 nRecips = xSimpleMailMessage->getCcRecipient( ).getLength( ); - nRecips += xSimpleMailMessage->getBccRecipient( ).getLength( ); + rCommandArgs.push_back(ATTACH); + rCommandArgs.push_back(sysPath); + } - if ( xSimpleMailMessage->getRecipient( ).getLength( ) ) - nRecips += 1; + if (!(aFlag & NO_USER_INTERFACE)) + rCommandArgs.push_back(FLAG_MAPI_DIALOG); - return nRecips; + if (!(aFlag & NO_LOGON_DIALOG)) + rCommandArgs.push_back(FLAG_MAPI_LOGON_UI); } -//------------------------------------------------ -// -//------------------------------------------------ - -void CSmplMailClient::initRecipientList( - const Sequence< rtl::OUString >& aRecipList, - ULONG ulRecipClass, - size_t& nPos ) +void SAL_CALL CSmplMailClient::sendSimpleMailMessage( + const Reference<XSimpleMailMessage>& xSimpleMailMessage, sal_Int32 aFlag) + throw (IllegalArgumentException, Exception, RuntimeException) { - OSL_PRECOND( nPos < m_RecipientList.size( ), "Wrong index" ); - - for( sal_Int32 i = 0; i < aRecipList.getLength( ); i++ ) - { - m_RecipsSmtpAddressList.push_back( - getSmtpPrefixedEmailAddress( aRecipList[i] ) ); + validateParameter(xSimpleMailMessage, aFlag); - m_RecipientList[nPos].ulRecipClass = ulRecipClass; - m_RecipientList[nPos].lpszName = - const_cast< LPSTR >( m_RecipsSmtpAddressList.back( ).getStr( ) + LEN_SMTP_PREFIX ); - m_RecipientList[nPos].lpszAddress = - const_cast< LPSTR >( m_RecipsSmtpAddressList.back( ).getStr( ) ); + StringList_t senddocParams; + assembleCommandLine(xSimpleMailMessage, aFlag, senddocParams); - nPos++; - } + if (!executeSenddoc(senddocParams)) + throw Exception( + rtl::OUString::createFromAscii("Send email failed"), + static_cast<XSimpleMailClient*>(this)); } -//------------------------------------------------ -// -//------------------------------------------------ - -void CSmplMailClient::initAttachementList( - const Reference< XSimpleMailMessage >& xSimpleMailMessage ) +void CSmplMailClient::validateParameter( + const Reference<XSimpleMailMessage>& xSimpleMailMessage, sal_Int32 aFlag ) { - Sequence< OUString > aAttachementList = - xSimpleMailMessage->getAttachement( ); - - sal_uInt32 nAttachements = aAttachementList.getLength( ); - - // avoid old entries - m_AttchmtsSysPathList.clear( ); - m_AttachementList.realloc( nAttachements ); - m_AttachementList.clean( ); - - OUString aSysPath; - for ( sal_uInt32 i = 0; i < nAttachements; i++ ) - { - osl::FileBase::RC rc = - osl::FileBase::getSystemPathFromFileURL( - aAttachementList[i], aSysPath ); - - if ( osl::FileBase::RC::E_None != rc ) - throw IllegalArgumentException( - OUString::createFromAscii( " " ), - static_cast< XSimpleMailClient* >( this ), - 1 ); - - m_AttchmtsSysPathList.push_back( - OString( - aSysPath.getStr( ), - aSysPath.getLength( ), - osl_getThreadTextEncoding( ) ) ); - - m_AttachementList[i].lpszPathName = const_cast< LPSTR >( - m_AttchmtsSysPathList.back( ).getStr( ) ); - m_AttachementList[i].nPosition = -1; - } -} - -//------------------------------------------------ -// -//------------------------------------------------ + if (!xSimpleMailMessage.is()) + throw IllegalArgumentException( + rtl::OUString::createFromAscii("Empty mail message reference"), + static_cast<XSimpleMailClient*>(this), + 1); -void CSmplMailClient::initMapiSendMailFlags( sal_Int32 aFlags, FLAGS& aMapiFlags ) -{ // #93077# - OSL_ENSURE( !( aFlags & NO_LOGON_DIALOG ), "Flag NO_LOGON_DIALOG has currently no effect" ); - - aMapiFlags = 0; // we should not use MAPI_UNICODE else - // Netscape interprets all string as UNICODE! - // #93077# MAPI_NEW_SESSION - - if ( !( aFlags & NO_USER_INTERFACE ) ) - aMapiFlags |= MAPI_DIALOG; - - if ( !( aFlags & NO_LOGON_DIALOG ) ) - aMapiFlags |= MAPI_LOGON_UI; -} - -//------------------------------------------------ -// -//------------------------------------------------ + OSL_ENSURE(!(aFlag & NO_LOGON_DIALOG), "Flag NO_LOGON_DIALOG has currently no effect"); -rtl::OUString CSmplMailClient::getMapiErrorMsg( ULONG ulMapiError ) -{ - LPVOID lpMsgBuff; - DWORD dwRet = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, - GetModuleHandleA( "mapi32.dll" ), - ulMapiError, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast< LPSTR >( &lpMsgBuff ), - 0, - NULL ); - - OUString errMsg; - - if ( dwRet ) - { - errMsg = OUString::createFromAscii( - static_cast< LPSTR >( lpMsgBuff ) ); - LocalFree( lpMsgBuff ); - } + // check the flags, the allowed range is 0 - (2^n - 1) + if (aFlag < 0 || aFlag > 3) + throw IllegalArgumentException( + rtl::OUString::createFromAscii("Invalid flag value"), + static_cast<XSimpleMailClient*>(this), + 2); - return errMsg; + // check if a recipient is specified of the flags NO_USER_INTERFACE is specified + if ((aFlag & NO_USER_INTERFACE) && !xSimpleMailMessage->getRecipient().getLength()) + throw IllegalArgumentException( + rtl::OUString::createFromAscii("No recipient specified"), + static_cast<XSimpleMailClient*>(this), + 1); } |