diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sfx2/source/dialog/mailmodel.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sfx2/source/dialog/mailmodel.cxx')
-rw-r--r-- | sfx2/source/dialog/mailmodel.cxx | 846 |
1 files changed, 846 insertions, 0 deletions
diff --git a/sfx2/source/dialog/mailmodel.cxx b/sfx2/source/dialog/mailmodel.cxx new file mode 100644 index 000000000..63e29270d --- /dev/null +++ b/sfx2/source/dialog/mailmodel.cxx @@ -0,0 +1,846 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/container/XContainerQuery.hpp> +#include <com/sun/star/document/XExporter.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XStatusListener.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/system/SimpleSystemMail.hpp> +#include <com/sun/star/system/SimpleCommandMail.hpp> +#include <com/sun/star/system/XSimpleMailClientSupplier.hpp> +#include <com/sun/star/system/SimpleMailClientFlags.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/util/URLTransformer.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <vcl/weld.hxx> +#include <osl/diagnose.h> + +#include <sfx2/mailmodelapi.hxx> +#include <sfx2/sfxresid.hxx> +#include <sfx2/strings.hrc> + +#include <unotools/tempfile.hxx> +#include <tools/urlobj.hxx> +#include <unotools/useroptions.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/string.hxx> +#include <vcl/svapp.hxx> +#include <cppuhelper/implbase.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::system; + +namespace { + +// - class PrepareListener_Impl ------------------------------------------ +class PrepareListener_Impl : public ::cppu::WeakImplHelper< css::frame::XStatusListener > +{ + bool m_bState; +public: + PrepareListener_Impl(); + + // css.frame.XStatusListener + virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& aEvent) override; + + // css.lang.XEventListener + virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) override; + + bool IsSet() const {return m_bState;} +}; + +} + +PrepareListener_Impl::PrepareListener_Impl() : + m_bState( false ) +{ +} + +void PrepareListener_Impl::statusChanged(const css::frame::FeatureStateEvent& rEvent) +{ + if( rEvent.IsEnabled ) + rEvent.State >>= m_bState; + else + m_bState = false; +} + +void PrepareListener_Impl::disposing(const css::lang::EventObject& /*rEvent*/) +{ +} + +// class SfxMailModel ----------------------------------------------- + +static const char PDF_DOCUMENT_TYPE[] = "pdf_Portable_Document_Format"; + +SfxMailModel::SaveResult SfxMailModel::ShowFilterOptionsDialog( + const uno::Reference< lang::XMultiServiceFactory >& xSMGR, + const uno::Reference< frame::XModel >& xModel, + const OUString& rFilterName, + const OUString& rType, + bool bModified, + sal_Int32& rNumArgs, + css::uno::Sequence< css::beans::PropertyValue >& rArgs ) +{ + SaveResult eRet( SAVE_ERROR ); + + try + { + uno::Sequence < beans::PropertyValue > aProps; + css::uno::Reference< css::container::XNameAccess > xFilterCFG( + xSMGR->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY ); + css::uno::Reference< css::util::XModifiable > xModifiable( xModel, css::uno::UNO_QUERY ); + + if ( !xFilterCFG.is() ) + return eRet; + + uno::Any aAny = xFilterCFG->getByName( rFilterName ); + + if ( aAny >>= aProps ) + { + for( const auto& rProp : std::as_const(aProps) ) + { + if( rProp.Name == "UIComponent" ) + { + OUString aServiceName; + rProp.Value >>= aServiceName; + if( !aServiceName.isEmpty() ) + { + uno::Reference< ui::dialogs::XExecutableDialog > xFilterDialog( + xSMGR->createInstance( aServiceName ), uno::UNO_QUERY ); + uno::Reference< beans::XPropertyAccess > xFilterProperties( + xFilterDialog, uno::UNO_QUERY ); + + if( xFilterDialog.is() && xFilterProperties.is() ) + { + uno::Sequence< beans::PropertyValue > aPropsForDialog(1); + uno::Reference< document::XExporter > xExporter( xFilterDialog, uno::UNO_QUERY ); + + if ( rType == PDF_DOCUMENT_TYPE ) + { + //add an internal property, used to tell the dialog we want to set a different + //string for the ok button + //used in filter/source/pdf/impdialog.cxx + uno::Sequence< beans::PropertyValue > aFilterDataValue(1); + aFilterDataValue[0].Name = "_OkButtonString"; + aFilterDataValue[0].Value <<= SfxResId(STR_PDF_EXPORT_SEND ); + + //add to the filterdata property, the only one the PDF export filter dialog will care for + aPropsForDialog[0].Name = "FilterData"; + aPropsForDialog[0].Value <<= aFilterDataValue; + + //when executing the dialog will merge the persistent FilterData properties + xFilterProperties->setPropertyValues( aPropsForDialog ); + } + + if( xExporter.is() ) + xExporter->setSourceDocument( xModel ); + + if( xFilterDialog->execute() ) + { + //get the filter data + uno::Sequence< beans::PropertyValue > aPropsFromDialog = xFilterProperties->getPropertyValues(); + + //add them to the args + auto pProp = std::find_if(aPropsFromDialog.begin(), aPropsFromDialog.end(), + [](const beans::PropertyValue& rDialogProp) { return rDialogProp.Name == "FilterData"; }); + if (pProp != aPropsFromDialog.end()) + { + //found the filterdata, add to the storing argument + rArgs.realloc( ++rNumArgs ); + rArgs[rNumArgs-1].Name = pProp->Name; + rArgs[rNumArgs-1].Value = pProp->Value; + } + eRet = SAVE_SUCCESSFULL; + } + else + { + // cancel from dialog, then do not send + // If the model is not modified, it could be modified by the dispatch calls. + // Therefore set back to modified = false. This should not hurt if we call + // on a non-modified model. + if ( !bModified ) + { + try + { + xModifiable->setModified( false ); + } + catch( css::beans::PropertyVetoException& ) + { + } + } + eRet = SAVE_CANCELLED; + } + } + break; + } + } + } + } + } + catch( css::uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + } + + return eRet; +} + +bool SfxMailModel::IsEmpty() const +{ + return maAttachedDocuments.empty(); +} + +SfxMailModel::SaveResult SfxMailModel::SaveDocumentAsFormat( + const OUString& aSaveFileName, + const css::uno::Reference< css::uno::XInterface >& xFrameOrModel, + const OUString& rType, + OUString& rFileNamePath ) +{ + SaveResult eRet( SAVE_ERROR ); + bool bSendAsPDF = ( rType == PDF_DOCUMENT_TYPE ); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + if (!xContext.is()) + return eRet; + + css::uno::Reference< css::frame::XModuleManager2 > xModuleManager( css::frame::ModuleManager::create(xContext) ); + + OUString aModule; + try + { + aModule = xModuleManager->identify( xFrameOrModel ); + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + + css::uno::Reference< css::frame::XFrame > xFrame( xFrameOrModel, css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XModel > xModel( xFrameOrModel, css::uno::UNO_QUERY ); + if ( xFrame.is() ) + { + css::uno::Reference< css::frame::XController > xController = xFrame->getController(); + if ( xController.is() ) + xModel = xController->getModel(); + } + + // We need at least a valid module name and model reference + if ( !aModule.isEmpty() && xModel.is() ) + { + bool bModified( false ); + bool bHasLocation( false ); + bool bStoreTo( false ); + + css::uno::Reference< css::util::XModifiable > xModifiable( xModel, css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XStorable > xStorable( xModel, css::uno::UNO_QUERY ); + + if ( xModifiable.is() ) + bModified = xModifiable->isModified(); + if ( xStorable.is() ) + { + OUString aLocation = xStorable->getLocation(); + INetURLObject aFileObj( aLocation ); + + bool bPrivateProtocol = ( aFileObj.GetProtocol() == INetProtocol::PrivSoffice ); + + bHasLocation = !aLocation.isEmpty() && !bPrivateProtocol; + OSL_ASSERT( !bPrivateProtocol ); + } + if ( !rType.isEmpty() ) + bStoreTo = true; + + if ( xStorable.is() ) + { + OUString aFilterName; + OUString aTypeName( rType ); + OUString aFileName; + OUString aExtension; + + css::uno::Reference< css::container::XContainerQuery > xContainerQuery( + xSMGR->createInstance( "com.sun.star.document.FilterFactory" ), + css::uno::UNO_QUERY ); + + if ( bStoreTo ) + { + // Retrieve filter from type + css::uno::Sequence< css::beans::NamedValue > aQuery( bSendAsPDF ? 3 : 2 ); + aQuery[0].Name = "Type"; + aQuery[0].Value <<= aTypeName; + aQuery[1].Name = "DocumentService"; + aQuery[1].Value <<= aModule; + if( bSendAsPDF ) + { + // #i91419# + // FIXME: we want just an export filter. However currently we need + // exact flag value as detailed in the filter configuration to get it + // this seems to be a bug + // without flags we get an import filter here, which is also unwanted + aQuery[2].Name = "Flags"; + aQuery[2].Value <<= sal_Int32(0x80042); // EXPORT ALIEN 3RDPARTY + } + + css::uno::Reference< css::container::XEnumeration > xEnumeration = + xContainerQuery->createSubSetEnumerationByProperties( aQuery ); + + if ( xEnumeration->hasMoreElements() ) + { + ::comphelper::SequenceAsHashMap aFilterPropsHM( xEnumeration->nextElement() ); + aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( + "Name", + OUString() ); + } + + if ( bHasLocation ) + { + // Retrieve filter from media descriptor + ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); + OUString aOrgFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault( + "FilterName", + OUString() ); + if ( aOrgFilterName == aFilterName ) + { + // We should save the document in the original format. Therefore this + // is not a storeTo operation. To support signing in this case, reset + // bStoreTo flag. + bStoreTo = false; + } + } + } + else + { + if ( bHasLocation ) + { + // Retrieve filter from media descriptor + ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); + aFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault( + "FilterName", + OUString() ); + } + + if ( !bHasLocation || aFilterName.isEmpty()) + { + // Retrieve the user defined default filter + try + { + ::comphelper::SequenceAsHashMap aFilterPropsHM( xModuleManager->getByName( aModule ) ); + aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( + "ooSetupFactoryDefaultFilter", + OUString() ); + css::uno::Reference< css::container::XNameAccess > xNameAccess( + xContainerQuery, css::uno::UNO_QUERY ); + if ( xNameAccess.is() ) + { + ::comphelper::SequenceAsHashMap aFilterPropsHM2( xNameAccess->getByName( aFilterName ) ); + aTypeName = aFilterPropsHM2.getUnpackedValueOrDefault( + "Type", + OUString() ); + } + } + catch ( css::container::NoSuchElementException& ) + { + } + catch ( css::beans::UnknownPropertyException& ) + { + } + } + } + + // No filter found => error + // No type and no location => error + if (( aFilterName.isEmpty() ) || + ( aTypeName.isEmpty() && !bHasLocation )) + return eRet; + + // Determine file name and extension + if ( bHasLocation && !bStoreTo ) + { + INetURLObject aFileObj( xStorable->getLocation() ); + aExtension = aFileObj.getExtension(); + } + else + { + css::uno::Reference< container::XNameAccess > xTypeDetection( + xSMGR->createInstance( "com.sun.star.document.TypeDetection" ), + css::uno::UNO_QUERY ); + + + if ( xTypeDetection.is() ) + { + try + { + ::comphelper::SequenceAsHashMap aTypeNamePropsHM( xTypeDetection->getByName( aTypeName ) ); + uno::Sequence< OUString > aExtensions = aTypeNamePropsHM.getUnpackedValueOrDefault( + "Extensions", + ::uno::Sequence< OUString >() ); + if ( aExtensions.hasElements() ) + aExtension = aExtensions[0]; + } + catch ( css::container::NoSuchElementException& ) + { + } + } + } + + // Use provided save file name. If empty determine file name + aFileName = aSaveFileName; + if ( aFileName.isEmpty() ) + { + if ( !bHasLocation ) + { + // Create a noname file name with the correct extension + const OUString aNoNameFileName( "noname" ); + aFileName = aNoNameFileName; + } + else + { + // Determine file name from model + INetURLObject aFileObj( xStorable->getLocation() ); + aFileName = aFileObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::NONE ); + } + } + + // No file name => error + if ( aFileName.isEmpty() ) + return eRet; + + OSL_ASSERT( !aFilterName.isEmpty() ); + OSL_ASSERT( !aFileName.isEmpty() ); + + // Creates a temporary directory to store a predefined file into it. + // This makes it possible to store the file for "send document as e-mail" + // with the original file name. We cannot use the original file as + // some mail programs need exclusive access. + ::utl::TempFile aTempDir( nullptr, true ); + + INetURLObject aFilePathObj( aTempDir.GetURL() ); + aFilePathObj.insertName( aFileName ); + aFilePathObj.setExtension( aExtension ); + + OUString aFileURL = aFilePathObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + + sal_Int32 nNumArgs(0); + const OUString aPasswordPropName( "Password" ); + css::uno::Sequence< css::beans::PropertyValue > aArgs( ++nNumArgs ); + aArgs[nNumArgs-1].Name = "FilterName"; + aArgs[nNumArgs-1].Value <<= aFilterName; + + ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); + OUString aPassword = aMediaDescrPropsHM.getUnpackedValueOrDefault( + aPasswordPropName, + OUString() ); + if ( !aPassword.isEmpty() ) + { + aArgs.realloc( ++nNumArgs ); + aArgs[nNumArgs-1].Name = aPasswordPropName; + aArgs[nNumArgs-1].Value <<= aPassword; + } + + bool bNeedsPreparation = false; + css::util::URL aPrepareURL; + css::uno::Reference< css::frame::XDispatch > xPrepareDispatch; + css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( xFrame, css::uno::UNO_QUERY ); + css::uno::Reference< css::util::XURLTransformer > xURLTransformer( css::util::URLTransformer::create( xContext ) ); + if( !bSendAsPDF ) + { + try + { + // check if the document needs to be prepared for sending as mail (embedding of links, removal of invisible content) + + aPrepareURL.Complete = ".uno:PrepareMailExport"; + xURLTransformer->parseStrict( aPrepareURL ); + + if ( xDispatchProvider.is() ) + { + xPrepareDispatch.set( xDispatchProvider->queryDispatch( aPrepareURL, OUString(), 0 )); + if ( xPrepareDispatch.is() ) + { + PrepareListener_Impl* pPrepareListener = new PrepareListener_Impl; + uno::Reference< css::frame::XStatusListener > xStatusListener = pPrepareListener; + xPrepareDispatch->addStatusListener( xStatusListener, aPrepareURL ); + bNeedsPreparation = pPrepareListener->IsSet(); + xPrepareDispatch->removeStatusListener( xStatusListener, aPrepareURL ); + } + } + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + } + + if ( bModified || !bHasLocation || bStoreTo || bNeedsPreparation ) + { + // Document is modified, is newly created or should be stored in a special format + try + { + if( bNeedsPreparation && xPrepareDispatch.is() ) + { + try + { + css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs; + xPrepareDispatch->dispatch( aPrepareURL, aDispatchArgs ); + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + } + + //check if this is the pdf output filter (i#64555) + if( bSendAsPDF ) + { + SaveResult eShowPDFFilterDialog = ShowFilterOptionsDialog( + xSMGR, xModel, aFilterName, rType, bModified, nNumArgs, aArgs ); + + // don't continue on dialog cancel or error + if ( eShowPDFFilterDialog != SAVE_SUCCESSFULL ) + return eShowPDFFilterDialog; + } + + xStorable->storeToURL( aFileURL, aArgs ); + rFileNamePath = aFileURL; + eRet = SAVE_SUCCESSFULL; + + if( !bSendAsPDF ) + { + css::util::URL aURL; + // #i30432# notify that export is finished - the Writer may want to restore removed content + aURL.Complete = ".uno:MailExportFinished"; + xURLTransformer->parseStrict( aURL ); + + if ( xDispatchProvider.is() ) + { + css::uno::Reference< css::frame::XDispatch > xDispatch( + xDispatchProvider->queryDispatch( aURL, OUString(), 0 )); + if ( xDispatch.is() ) + { + try + { + css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs; + xDispatch->dispatch( aURL, aDispatchArgs ); + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + } + } + } + // If the model is not modified, it could be modified by the dispatch calls. + // Therefore set back to modified = false. This should not hurt if we call + // on a non-modified model. + if ( !bModified ) + { + try + { + xModifiable->setModified( false ); + } + catch( css::beans::PropertyVetoException& ) + { + } + } + } + catch ( css::io::IOException& ) + { + eRet = SAVE_ERROR; + } + } + else + { + // We need 1:1 copy of the document to preserve an added signature. + aArgs.realloc( ++nNumArgs ); + aArgs[nNumArgs-1].Name = "CopyStreamIfPossible"; + aArgs[nNumArgs-1].Value <<= true; + + try + { + xStorable->storeToURL( aFileURL, aArgs ); + rFileNamePath = aFileURL; + eRet = SAVE_SUCCESSFULL; + } + catch ( css::io::IOException& ) + { + eRet = SAVE_ERROR; + } + } + } + } + + return eRet; +} + +SfxMailModel::SfxMailModel() +{ +} + +SfxMailModel::~SfxMailModel() +{ +} + +void SfxMailModel::AddToAddress( const OUString& rAddress ) +{ + // don't add an empty address + if ( !rAddress.isEmpty() ) + { + if ( !mpToList ) + // create the list + mpToList.reset(new AddressList_Impl); + + // add address to list + mpToList->push_back( rAddress ); + } +} + +SfxMailModel::SendMailResult SfxMailModel::AttachDocument( + const css::uno::Reference< css::uno::XInterface >& xFrameOrModel, + const OUString& sAttachmentTitle ) +{ + OUString sFileName; + + SaveResult eSaveResult = SaveDocumentAsFormat( sAttachmentTitle, xFrameOrModel, OUString()/*sDocumentType*/, sFileName ); + if ( eSaveResult == SAVE_SUCCESSFULL && !sFileName.isEmpty() ) + maAttachedDocuments.push_back(sFileName); + return eSaveResult == SAVE_SUCCESSFULL ? SEND_MAIL_OK : SEND_MAIL_ERROR; +} + +SfxMailModel::SendMailResult SfxMailModel::Send( const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + OSL_ENSURE(!maAttachedDocuments.empty(),"No document added!"); + SendMailResult eResult = SEND_MAIL_ERROR; + if ( !maAttachedDocuments.empty() ) + { + css::uno::Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + + css::uno::Reference< XSimpleMailClientSupplier > xSimpleMailClientSupplier; + + // Prefer the SimpleSystemMail service if available + try { + xSimpleMailClientSupplier = SimpleSystemMail::create( xContext ); + } + catch ( const uno::Exception & ) + {} + + if ( ! xSimpleMailClientSupplier.is() ) + { + try { + xSimpleMailClientSupplier = SimpleCommandMail::create( xContext ); + } + catch ( const uno::Exception & ) + {} + } + + if ( xSimpleMailClientSupplier.is() ) + { + css::uno::Reference< XSimpleMailClient > xSimpleMailClient = xSimpleMailClientSupplier->querySimpleMailClient(); + + if ( !xSimpleMailClient.is() ) + { + // no mail client support => message box! + return SEND_MAIL_ERROR; + } + + // we have a simple mail client + css::uno::Reference< XSimpleMailMessage > xSimpleMailMessage = xSimpleMailClient->createSimpleMailMessage(); + if ( xSimpleMailMessage.is() ) + { + sal_Int32 nSendFlags = SimpleMailClientFlags::DEFAULTS; + if ( maFromAddress.isEmpty() ) + { + // from address not set, try figure out users e-mail address + CreateFromAddress_Impl( maFromAddress ); + } + xSimpleMailMessage->setOriginator( maFromAddress ); + + size_t nToCount = mpToList ? mpToList->size() : 0; + + // set recipient (only one) for this simple mail server!! + if ( nToCount >= 1 ) + { + xSimpleMailMessage->setRecipient( mpToList->at( 0 ) ); + nSendFlags = SimpleMailClientFlags::NO_USER_INTERFACE; + } + + // all other recipient must be handled with CC recipients! + if ( nToCount > 1 ) + { + Sequence< OUString > aCcRecipientSeq( nToCount - 1 ); + for ( size_t i = 1; i < nToCount; ++i ) + aCcRecipientSeq[i - 1] = mpToList->at(i); + xSimpleMailMessage->setCcRecipient( aCcRecipientSeq ); + } + + Sequence< OUString > aAttachmentSeq(maAttachedDocuments.data(),maAttachedDocuments.size()); + + if ( xSimpleMailMessage->getSubject().isEmpty() ) { + INetURLObject url( + maAttachedDocuments[0], INetURLObject::EncodeMechanism::WasEncoded); + OUString subject( + url.getBase( + INetURLObject::LAST_SEGMENT, false, + INetURLObject::DecodeMechanism::WithCharset)); + if (subject.isEmpty()) { + subject = maAttachedDocuments[0]; + } + if ( maAttachedDocuments.size() > 1 ) + subject += ", ..."; + xSimpleMailMessage->setSubject( subject ); + } + xSimpleMailMessage->setAttachement( aAttachmentSeq ); + + bool bSend( false ); + try + { + xSimpleMailClient->sendSimpleMailMessage( xSimpleMailMessage, nSendFlags ); + bSend = true; + } + catch ( IllegalArgumentException& ) + { + } + catch ( Exception& ) + { + } + + if ( !bSend ) + { + css::uno::Reference< css::awt::XWindow > xParentWindow = xFrame->getContainerWindow(); + + SolarMutexGuard aGuard; + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(Application::GetFrameWeld(xParentWindow), "sfx/ui/errorfindemaildialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("ErrorFindEmailDialog")); + xBox->run(); + eResult = SEND_MAIL_CANCELLED; + } + else + eResult = SEND_MAIL_OK; + } + } + } + else + eResult = SEND_MAIL_CANCELLED; + + return eResult; +} + +SfxMailModel::SendMailResult SfxMailModel::SaveAndSend( const css::uno::Reference< css::frame::XFrame >& xFrame, const OUString& rTypeName ) +{ + SaveResult eSaveResult; + SendMailResult eResult = SEND_MAIL_ERROR; + OUString aFileName; + + eSaveResult = SaveDocumentAsFormat( OUString(), xFrame, rTypeName, aFileName ); + + if ( eSaveResult == SAVE_SUCCESSFULL ) + { + maAttachedDocuments.push_back( aFileName ); + return Send( xFrame ); + } + else if ( eSaveResult == SAVE_CANCELLED ) + eResult = SEND_MAIL_CANCELLED; + + return eResult; +} + +// functions ------------------------------------------------------------- + +bool CreateFromAddress_Impl( OUString& rFrom ) + +/* [Description] + + This function tries to create a From-address with the help of IniManagers. + For this the fields 'first name', 'Name' and 'Email' are read from the + application-ini-data. If these fields are not set, FALSE is returned. + + [Return value] + + sal_True: Address could be created. + sal_False: Address could not be created. +*/ + +{ + SvtUserOptions aUserCFG; + OUString aName = aUserCFG.GetLastName (); + OUString aFirstName = aUserCFG.GetFirstName (); + if ( !aFirstName.isEmpty() || !aName.isEmpty() ) + { + if ( !aFirstName.isEmpty() ) + { + rFrom = comphelper::string::strip(aFirstName, ' '); + + if ( !aName.isEmpty() ) + rFrom += " "; + } + rFrom += comphelper::string::strip(aName, ' '); + // remove illegal characters + rFrom = rFrom.replaceAll("<", "").replaceAll(">", "").replaceAll("@", ""); + } + OUString aEmailName = aUserCFG.GetEmail(); + + // remove illegal characters + aEmailName = aEmailName.replaceAll("<", "").replaceAll(">", ""); + + if ( !aEmailName.isEmpty() ) + { + if ( !rFrom.isEmpty() ) + rFrom += " "; + rFrom += "<" + comphelper::string::strip(aEmailName, ' ') + ">"; + } + else + rFrom.clear(); + return !rFrom.isEmpty(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |