1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/beans/PropertyValue.hpp>
21 #include <com/sun/star/beans/XPropertyAccess.hpp>
22 #include <com/sun/star/container/XContainerQuery.hpp>
23 #include <com/sun/star/document/XExporter.hpp>
24 #include <com/sun/star/embed/XStorage.hpp>
25 #include <com/sun/star/frame/XDispatchProvider.hpp>
26 #include <com/sun/star/frame/XDispatch.hpp>
27 #include <com/sun/star/frame/XStatusListener.hpp>
28 #include <com/sun/star/frame/XFrame.hpp>
29 #include <com/sun/star/frame/XModel.hpp>
30 #include <com/sun/star/frame/ModuleManager.hpp>
31 #include <com/sun/star/frame/XStorable.hpp>
32 #include <com/sun/star/io/IOException.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/system/SimpleSystemMail.hpp>
35 #include <com/sun/star/system/SimpleCommandMail.hpp>
36 #include <com/sun/star/system/XSimpleMailClientSupplier.hpp>
37 #include <com/sun/star/system/SimpleMailClientFlags.hpp>
38 #include <com/sun/star/ucb/CommandAbortedException.hpp>
39 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
40 #include <com/sun/star/uno/Reference.h>
41 #include <com/sun/star/util/URLTransformer.hpp>
42 #include <com/sun/star/util/XURLTransformer.hpp>
43 #include <com/sun/star/util/XModifiable.hpp>
44 #include <vcl/weld.hxx>
45 #include <osl/diagnose.h>
47 #include <sfx2/mailmodelapi.hxx>
48 #include <sfx2/sfxresid.hxx>
49 #include <sfx2/strings.hrc>
51 #include <unotools/tempfile.hxx>
52 #include <tools/urlobj.hxx>
53 #include <unotools/useroptions.hxx>
54 #include <comphelper/processfactory.hxx>
55 #include <comphelper/propertyvalue.hxx>
56 #include <comphelper/sequenceashashmap.hxx>
57 #include <comphelper/string.hxx>
58 #include <vcl/svapp.hxx>
59 #include <cppuhelper/implbase.hxx>
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::beans
;
64 using namespace ::com::sun::star::frame
;
65 using namespace ::com::sun::star::io
;
66 using namespace ::com::sun::star::lang
;
67 using namespace ::com::sun::star::ucb
;
68 using namespace ::com::sun::star::uno
;
69 using namespace ::com::sun::star::util
;
70 using namespace ::com::sun::star::system
;
74 // - class PrepareListener_Impl ------------------------------------------
75 class PrepareListener_Impl
: public ::cppu::WeakImplHelper
< css::frame::XStatusListener
>
79 PrepareListener_Impl();
81 // css.frame.XStatusListener
82 virtual void SAL_CALL
statusChanged(const css::frame::FeatureStateEvent
& aEvent
) override
;
84 // css.lang.XEventListener
85 virtual void SAL_CALL
disposing(const css::lang::EventObject
& aEvent
) override
;
87 bool IsSet() const {return m_bState
;}
92 PrepareListener_Impl::PrepareListener_Impl() :
97 void PrepareListener_Impl::statusChanged(const css::frame::FeatureStateEvent
& rEvent
)
99 if( rEvent
.IsEnabled
)
100 rEvent
.State
>>= m_bState
;
105 void PrepareListener_Impl::disposing(const css::lang::EventObject
& /*rEvent*/)
109 // class SfxMailModel -----------------------------------------------
111 const char16_t PDF_DOCUMENT_TYPE
[] = u
"pdf_Portable_Document_Format";
113 SfxMailModel::SaveResult
SfxMailModel::ShowFilterOptionsDialog(
114 const uno::Reference
< lang::XMultiServiceFactory
>& xSMGR
,
115 const uno::Reference
< frame::XModel
>& xModel
,
116 const OUString
& rFilterName
,
117 std::u16string_view rType
,
120 css::uno::Sequence
< css::beans::PropertyValue
>& rArgs
)
122 SaveResult
eRet( SAVE_ERROR
);
126 uno::Sequence
< beans::PropertyValue
> aProps
;
127 css::uno::Reference
< css::container::XNameAccess
> xFilterCFG(
128 xSMGR
->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY
);
129 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
131 if ( !xFilterCFG
.is() )
134 uno::Any aAny
= xFilterCFG
->getByName( rFilterName
);
136 if ( aAny
>>= aProps
)
138 for( const auto& rProp
: std::as_const(aProps
) )
140 if( rProp
.Name
== "UIComponent" )
142 OUString aServiceName
;
143 rProp
.Value
>>= aServiceName
;
144 if( !aServiceName
.isEmpty() )
146 uno::Reference
< ui::dialogs::XExecutableDialog
> xFilterDialog(
147 xSMGR
->createInstance( aServiceName
), uno::UNO_QUERY
);
148 uno::Reference
< beans::XPropertyAccess
> xFilterProperties(
149 xFilterDialog
, uno::UNO_QUERY
);
151 if( xFilterDialog
.is() && xFilterProperties
.is() )
153 uno::Reference
< document::XExporter
> xExporter( xFilterDialog
, uno::UNO_QUERY
);
155 if ( rType
== PDF_DOCUMENT_TYPE
)
157 //add an internal property, used to tell the dialog we want to set a different
158 //string for the ok button
159 //used in filter/source/pdf/impdialog.cxx
160 uno::Sequence
< beans::PropertyValue
> aFilterDataValue
{
161 comphelper::makePropertyValue("_OkButtonString",
162 SfxResId(STR_PDF_EXPORT_SEND
))
165 //add to the filterdata property, the only one the PDF export filter dialog will care for
166 uno::Sequence
< beans::PropertyValue
> aPropsForDialog
{
167 comphelper::makePropertyValue("FilterData", aFilterDataValue
)
170 //when executing the dialog will merge the persistent FilterData properties
171 xFilterProperties
->setPropertyValues( aPropsForDialog
);
175 xExporter
->setSourceDocument( xModel
);
177 if( xFilterDialog
->execute() )
179 //get the filter data
180 const uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
= xFilterProperties
->getPropertyValues();
182 //add them to the args
183 auto pProp
= std::find_if(aPropsFromDialog
.begin(), aPropsFromDialog
.end(),
184 [](const beans::PropertyValue
& rDialogProp
) { return rDialogProp
.Name
== "FilterData"; });
185 if (pProp
!= aPropsFromDialog
.end())
187 //found the filterdata, add to the storing argument
188 rArgs
.realloc( ++rNumArgs
);
189 auto pArgs
= rArgs
.getArray();
190 pArgs
[rNumArgs
-1].Name
= pProp
->Name
;
191 pArgs
[rNumArgs
-1].Value
= pProp
->Value
;
193 eRet
= SAVE_SUCCESSFUL
;
197 // cancel from dialog, then do not send
198 // If the model is not modified, it could be modified by the dispatch calls.
199 // Therefore set back to modified = false. This should not hurt if we call
200 // on a non-modified model.
205 xModifiable
->setModified( false );
207 catch( css::beans::PropertyVetoException
& )
211 eRet
= SAVE_CANCELLED
;
220 catch( css::uno::RuntimeException
& )
224 catch( uno::Exception
& )
231 bool SfxMailModel::IsEmpty() const
233 return maAttachedDocuments
.empty();
236 SfxMailModel::SaveResult
SfxMailModel::SaveDocumentAsFormat(
237 const OUString
& aSaveFileName
,
238 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
239 const OUString
& rType
,
240 OUString
& rFileNamePath
)
242 SaveResult
eRet( SAVE_ERROR
);
243 bool bSendAsPDF
= ( rType
== PDF_DOCUMENT_TYPE
);
245 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
246 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
250 css::uno::Reference
< css::frame::XModuleManager2
> xModuleManager( css::frame::ModuleManager::create(xContext
) );
255 aModule
= xModuleManager
->identify( xFrameOrModel
);
257 catch ( css::uno::RuntimeException
& )
261 catch ( css::uno::Exception
& )
265 css::uno::Reference
< css::frame::XFrame
> xFrame( xFrameOrModel
, css::uno::UNO_QUERY
);
266 css::uno::Reference
< css::frame::XModel
> xModel( xFrameOrModel
, css::uno::UNO_QUERY
);
269 css::uno::Reference
< css::frame::XController
> xController
= xFrame
->getController();
270 if ( xController
.is() )
271 xModel
= xController
->getModel();
274 // We need at least a valid module name and model reference
275 if ( !aModule
.isEmpty() && xModel
.is() )
277 bool bModified( false );
278 bool bHasLocation( false );
279 bool bStoreTo( false );
281 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
282 css::uno::Reference
< css::frame::XStorable
> xStorable( xModel
, css::uno::UNO_QUERY
);
284 if ( xModifiable
.is() )
285 bModified
= xModifiable
->isModified();
286 if ( xStorable
.is() )
288 OUString aLocation
= xStorable
->getLocation();
289 INetURLObject
aFileObj( aLocation
);
291 bool bPrivateProtocol
= ( aFileObj
.GetProtocol() == INetProtocol::PrivSoffice
);
293 bHasLocation
= !aLocation
.isEmpty() && !bPrivateProtocol
;
294 OSL_ASSERT( !bPrivateProtocol
);
296 if ( !rType
.isEmpty() )
299 if ( xStorable
.is() )
301 OUString aFilterName
;
302 OUString
aTypeName( rType
);
306 css::uno::Reference
< css::container::XContainerQuery
> xContainerQuery(
307 xSMGR
->createInstance( "com.sun.star.document.FilterFactory" ),
308 css::uno::UNO_QUERY
);
312 // Retrieve filter from type
313 css::uno::Sequence
< css::beans::NamedValue
> aQuery( bSendAsPDF
? 3 : 2 );
314 auto pQuery
= aQuery
.getArray();
315 pQuery
[0].Name
= "Type";
316 pQuery
[0].Value
<<= aTypeName
;
317 pQuery
[1].Name
= "DocumentService";
318 pQuery
[1].Value
<<= aModule
;
322 // FIXME: we want just an export filter. However currently we need
323 // exact flag value as detailed in the filter configuration to get it
324 // this seems to be a bug
325 // without flags we get an import filter here, which is also unwanted
326 pQuery
[2].Name
= "Flags";
327 pQuery
[2].Value
<<= sal_Int32(0x80042); // SfxFilterFlags: EXPORT ALIEN 3RDPARTY
330 css::uno::Reference
< css::container::XEnumeration
> xEnumeration
=
331 xContainerQuery
->createSubSetEnumerationByProperties( aQuery
);
333 if ( xEnumeration
->hasMoreElements() )
335 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xEnumeration
->nextElement() );
336 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
343 // Retrieve filter from media descriptor
344 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
345 OUString aOrgFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
348 if ( aOrgFilterName
== aFilterName
)
350 // We should save the document in the original format. Therefore this
351 // is not a storeTo operation. To support signing in this case, reset
361 // Retrieve filter from media descriptor
362 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
363 aFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
368 if ( !bHasLocation
|| aFilterName
.isEmpty())
370 // Retrieve the user defined default filter
373 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xModuleManager
->getByName( aModule
) );
374 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
375 "ooSetupFactoryDefaultFilter",
377 css::uno::Reference
< css::container::XNameAccess
> xNameAccess(
378 xContainerQuery
, css::uno::UNO_QUERY
);
379 if ( xNameAccess
.is() )
381 ::comphelper::SequenceAsHashMap
aFilterPropsHM2( xNameAccess
->getByName( aFilterName
) );
382 aTypeName
= aFilterPropsHM2
.getUnpackedValueOrDefault(
387 catch ( css::container::NoSuchElementException
& )
390 catch ( css::beans::UnknownPropertyException
& )
396 // No filter found => error
397 // No type and no location => error
398 if (( aFilterName
.isEmpty() ) ||
399 ( aTypeName
.isEmpty() && !bHasLocation
))
402 // Determine file name and extension
403 if ( bHasLocation
&& !bStoreTo
)
405 INetURLObject
aFileObj( xStorable
->getLocation() );
406 aExtension
= aFileObj
.getExtension();
410 css::uno::Reference
< container::XNameAccess
> xTypeDetection(
411 xSMGR
->createInstance( "com.sun.star.document.TypeDetection" ),
412 css::uno::UNO_QUERY
);
415 if ( xTypeDetection
.is() )
419 ::comphelper::SequenceAsHashMap
aTypeNamePropsHM( xTypeDetection
->getByName( aTypeName
) );
420 uno::Sequence
< OUString
> aExtensions
= aTypeNamePropsHM
.getUnpackedValueOrDefault(
422 ::uno::Sequence
< OUString
>() );
423 if ( aExtensions
.hasElements() )
424 aExtension
= aExtensions
[0];
426 catch ( css::container::NoSuchElementException
& )
432 // Use provided save file name. If empty determine file name
433 aFileName
= aSaveFileName
;
434 if ( aFileName
.isEmpty() )
438 // Create a noname file name with the correct extension
439 aFileName
= "noname";
443 // Determine file name from model
444 INetURLObject
aFileObj( xStorable
->getLocation() );
445 aFileName
= aFileObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DecodeMechanism::NONE
);
449 // No file name => error
450 if ( aFileName
.isEmpty() )
453 OSL_ASSERT( !aFilterName
.isEmpty() );
454 OSL_ASSERT( !aFileName
.isEmpty() );
456 // Creates a temporary directory to store a predefined file into it.
457 // This makes it possible to store the file for "send document as e-mail"
458 // with the original file name. We cannot use the original file as
459 // some mail programs need exclusive access.
460 ::utl::TempFile
aTempDir( nullptr, true );
462 INetURLObject
aFilePathObj( aTempDir
.GetURL() );
463 aFilePathObj
.insertName( aFileName
);
464 aFilePathObj
.setExtension( aExtension
);
466 OUString aFileURL
= aFilePathObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
468 sal_Int32
nNumArgs(1);
469 static const OUStringLiteral
aPasswordPropName( u
"Password" );
470 css::uno::Sequence
< css::beans::PropertyValue
> aArgs
{ comphelper::makePropertyValue(
471 "FilterName", aFilterName
) };
473 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
474 OUString aPassword
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
477 if ( !aPassword
.isEmpty() )
479 aArgs
.realloc( ++nNumArgs
);
480 auto pArgs
= aArgs
.getArray();
481 pArgs
[nNumArgs
-1].Name
= aPasswordPropName
;
482 pArgs
[nNumArgs
-1].Value
<<= aPassword
;
485 bool bNeedsPreparation
= false;
486 css::util::URL aPrepareURL
;
487 css::uno::Reference
< css::frame::XDispatch
> xPrepareDispatch
;
488 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatchProvider( xFrame
, css::uno::UNO_QUERY
);
489 css::uno::Reference
< css::util::XURLTransformer
> xURLTransformer( css::util::URLTransformer::create( xContext
) );
494 // check if the document needs to be prepared for sending as mail (embedding of links, removal of invisible content)
496 aPrepareURL
.Complete
= ".uno:PrepareMailExport";
497 xURLTransformer
->parseStrict( aPrepareURL
);
499 if ( xDispatchProvider
.is() )
501 xPrepareDispatch
.set( xDispatchProvider
->queryDispatch( aPrepareURL
, OUString(), 0 ));
502 if ( xPrepareDispatch
.is() )
504 rtl::Reference
<PrepareListener_Impl
> pPrepareListener
= new PrepareListener_Impl
;
505 xPrepareDispatch
->addStatusListener( pPrepareListener
, aPrepareURL
);
506 bNeedsPreparation
= pPrepareListener
->IsSet();
507 xPrepareDispatch
->removeStatusListener( pPrepareListener
, aPrepareURL
);
511 catch ( css::uno::RuntimeException
& )
515 catch ( css::uno::Exception
& )
520 if ( bModified
|| !bHasLocation
|| bStoreTo
|| bNeedsPreparation
)
522 // Document is modified, is newly created or should be stored in a special format
525 if( bNeedsPreparation
&& xPrepareDispatch
.is() )
529 css::uno::Sequence
< css::beans::PropertyValue
> aDispatchArgs
;
530 xPrepareDispatch
->dispatch( aPrepareURL
, aDispatchArgs
);
532 catch ( css::uno::RuntimeException
& )
536 catch ( css::uno::Exception
& )
541 //check if this is the pdf output filter (i#64555)
544 SaveResult eShowPDFFilterDialog
= ShowFilterOptionsDialog(
545 xSMGR
, xModel
, aFilterName
, rType
, bModified
, nNumArgs
, aArgs
);
547 // don't continue on dialog cancel or error
548 if ( eShowPDFFilterDialog
!= SAVE_SUCCESSFUL
)
549 return eShowPDFFilterDialog
;
552 xStorable
->storeToURL( aFileURL
, aArgs
);
553 rFileNamePath
= aFileURL
;
554 eRet
= SAVE_SUCCESSFUL
;
559 // #i30432# notify that export is finished - the Writer may want to restore removed content
560 aURL
.Complete
= ".uno:MailExportFinished";
561 xURLTransformer
->parseStrict( aURL
);
563 if ( xDispatchProvider
.is() )
565 css::uno::Reference
< css::frame::XDispatch
> xDispatch(
566 xDispatchProvider
->queryDispatch( aURL
, OUString(), 0 ));
567 if ( xDispatch
.is() )
571 css::uno::Sequence
< css::beans::PropertyValue
> aDispatchArgs
;
572 xDispatch
->dispatch( aURL
, aDispatchArgs
);
574 catch ( css::uno::RuntimeException
& )
578 catch ( css::uno::Exception
& )
584 // If the model is not modified, it could be modified by the dispatch calls.
585 // Therefore set back to modified = false. This should not hurt if we call
586 // on a non-modified model.
591 xModifiable
->setModified( false );
593 catch( css::beans::PropertyVetoException
& )
598 catch ( css::io::IOException
& )
605 // We need 1:1 copy of the document to preserve an added signature.
606 aArgs
.realloc( ++nNumArgs
);
607 auto pArgs
= aArgs
.getArray();
608 pArgs
[nNumArgs
-1].Name
= "CopyStreamIfPossible";
609 pArgs
[nNumArgs
-1].Value
<<= true;
613 xStorable
->storeToURL( aFileURL
, aArgs
);
614 rFileNamePath
= aFileURL
;
615 eRet
= SAVE_SUCCESSFUL
;
617 catch ( css::io::IOException
& )
628 SfxMailModel::SfxMailModel()
632 SfxMailModel::~SfxMailModel()
636 void SfxMailModel::AddToAddress( const OUString
& rAddress
)
638 // don't add an empty address
639 if ( !rAddress
.isEmpty() )
643 mpToList
.reset(new AddressList_Impl
);
645 // add address to list
646 mpToList
->push_back( rAddress
);
650 SfxMailModel::SendMailResult
SfxMailModel::AttachDocument(
651 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
652 const OUString
& sAttachmentTitle
)
656 SaveResult eSaveResult
= SaveDocumentAsFormat( sAttachmentTitle
, xFrameOrModel
, OUString()/*sDocumentType*/, sFileName
);
657 if ( eSaveResult
== SAVE_SUCCESSFUL
&& !sFileName
.isEmpty() )
658 maAttachedDocuments
.push_back(sFileName
);
659 return eSaveResult
== SAVE_SUCCESSFUL
? SEND_MAIL_OK
: SEND_MAIL_ERROR
;
662 SfxMailModel::SendMailResult
SfxMailModel::Send( const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
664 OSL_ENSURE(!maAttachedDocuments
.empty(),"No document added!");
665 SendMailResult eResult
= SEND_MAIL_ERROR
;
666 if ( !maAttachedDocuments
.empty() )
668 css::uno::Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
670 css::uno::Reference
< XSimpleMailClientSupplier
> xSimpleMailClientSupplier
;
672 // Prefer the SimpleSystemMail service if available
674 xSimpleMailClientSupplier
= SimpleSystemMail::create( xContext
);
676 catch ( const uno::Exception
& )
679 if ( ! xSimpleMailClientSupplier
.is() )
682 xSimpleMailClientSupplier
= SimpleCommandMail::create( xContext
);
684 catch ( const uno::Exception
& )
688 if ( xSimpleMailClientSupplier
.is() )
690 css::uno::Reference
< XSimpleMailClient
> xSimpleMailClient
= xSimpleMailClientSupplier
->querySimpleMailClient();
692 if ( !xSimpleMailClient
.is() )
694 // no mail client support => message box!
695 return SEND_MAIL_ERROR
;
698 // we have a simple mail client
699 css::uno::Reference
< XSimpleMailMessage
> xSimpleMailMessage
= xSimpleMailClient
->createSimpleMailMessage();
700 if ( xSimpleMailMessage
.is() )
702 sal_Int32 nSendFlags
= SimpleMailClientFlags::DEFAULTS
;
703 if ( maFromAddress
.isEmpty() )
705 // from address not set, try figure out users e-mail address
706 CreateFromAddress_Impl( maFromAddress
);
708 xSimpleMailMessage
->setOriginator( maFromAddress
);
710 size_t nToCount
= mpToList
? mpToList
->size() : 0;
712 // set recipient (only one) for this simple mail server!!
715 xSimpleMailMessage
->setRecipient( mpToList
->at( 0 ) );
716 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
719 // all other recipient must be handled with CC recipients!
722 Sequence
< OUString
> aCcRecipientSeq( nToCount
- 1 );
723 std::copy_n(std::next(mpToList
->begin()), aCcRecipientSeq
.getLength(),
724 aCcRecipientSeq
.getArray());
725 xSimpleMailMessage
->setCcRecipient( aCcRecipientSeq
);
728 Sequence
< OUString
> aAttachmentSeq(maAttachedDocuments
.data(),maAttachedDocuments
.size());
730 if ( xSimpleMailMessage
->getSubject().isEmpty() ) {
732 maAttachedDocuments
[0], INetURLObject::EncodeMechanism::WasEncoded
);
735 INetURLObject::LAST_SEGMENT
, false,
736 INetURLObject::DecodeMechanism::WithCharset
));
737 if (subject
.isEmpty()) {
738 subject
= maAttachedDocuments
[0];
740 if ( maAttachedDocuments
.size() > 1 )
742 xSimpleMailMessage
->setSubject( subject
);
744 xSimpleMailMessage
->setAttachement( aAttachmentSeq
);
749 xSimpleMailClient
->sendSimpleMailMessage( xSimpleMailMessage
, nSendFlags
);
752 catch ( IllegalArgumentException
& )
761 css::uno::Reference
< css::awt::XWindow
> xParentWindow
= xFrame
->getContainerWindow();
763 SolarMutexGuard aGuard
;
765 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(Application::GetFrameWeld(xParentWindow
), "sfx/ui/errorfindemaildialog.ui"));
766 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("ErrorFindEmailDialog"));
768 eResult
= SEND_MAIL_CANCELLED
;
771 eResult
= SEND_MAIL_OK
;
776 eResult
= SEND_MAIL_CANCELLED
;
781 SfxMailModel::SendMailResult
SfxMailModel::SaveAndSend( const css::uno::Reference
< css::frame::XFrame
>& xFrame
, const OUString
& rTypeName
)
783 SaveResult eSaveResult
;
784 SendMailResult eResult
= SEND_MAIL_ERROR
;
787 eSaveResult
= SaveDocumentAsFormat( OUString(), xFrame
, rTypeName
, aFileName
);
789 if ( eSaveResult
== SAVE_SUCCESSFUL
)
791 maAttachedDocuments
.push_back( aFileName
);
792 return Send( xFrame
);
794 else if ( eSaveResult
== SAVE_CANCELLED
)
795 eResult
= SEND_MAIL_CANCELLED
;
800 // functions -------------------------------------------------------------
802 bool CreateFromAddress_Impl( OUString
& rFrom
)
806 This function tries to create a From-address with the help of IniManagers.
807 For this the fields 'first name', 'Name' and 'Email' are read from the
808 application-ini-data. If these fields are not set, FALSE is returned.
812 sal_True: Address could be created.
813 sal_False: Address could not be created.
817 SvtUserOptions aUserCFG
;
818 OUString aName
= aUserCFG
.GetLastName ();
819 OUString aFirstName
= aUserCFG
.GetFirstName ();
820 if ( !aFirstName
.isEmpty() || !aName
.isEmpty() )
822 if ( !aFirstName
.isEmpty() )
824 rFrom
= comphelper::string::strip(aFirstName
, ' ');
826 if ( !aName
.isEmpty() )
829 rFrom
+= comphelper::string::strip(aName
, ' ');
830 // remove illegal characters
831 rFrom
= rFrom
.replaceAll("<", "").replaceAll(">", "").replaceAll("@", "");
833 OUString aEmailName
= aUserCFG
.GetEmail();
835 // remove illegal characters
836 aEmailName
= aEmailName
.replaceAll("<", "").replaceAll(">", "");
838 if ( !aEmailName
.isEmpty() )
840 if ( !rFrom
.isEmpty() )
842 rFrom
+= "<" + comphelper::string::strip(aEmailName
, ' ') + ">";
846 return !rFrom
.isEmpty();
849 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */