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::uno
;
68 using namespace ::com::sun::star::util
;
69 using namespace ::com::sun::star::system
;
73 // - class PrepareListener_Impl ------------------------------------------
74 class PrepareListener_Impl
: public ::cppu::WeakImplHelper
< css::frame::XStatusListener
>
78 PrepareListener_Impl();
80 // css.frame.XStatusListener
81 virtual void SAL_CALL
statusChanged(const css::frame::FeatureStateEvent
& aEvent
) override
;
83 // css.lang.XEventListener
84 virtual void SAL_CALL
disposing(const css::lang::EventObject
& aEvent
) override
;
86 bool IsSet() const {return m_bState
;}
91 PrepareListener_Impl::PrepareListener_Impl() :
96 void PrepareListener_Impl::statusChanged(const css::frame::FeatureStateEvent
& rEvent
)
98 if( rEvent
.IsEnabled
)
99 rEvent
.State
>>= m_bState
;
104 void PrepareListener_Impl::disposing(const css::lang::EventObject
& /*rEvent*/)
108 // class SfxMailModel -----------------------------------------------
110 const char16_t PDF_DOCUMENT_TYPE
[] = u
"pdf_Portable_Document_Format";
112 SfxMailModel::SaveResult
SfxMailModel::ShowFilterOptionsDialog(
113 const uno::Reference
< lang::XMultiServiceFactory
>& xSMGR
,
114 const uno::Reference
< frame::XModel
>& xModel
,
115 const OUString
& rFilterName
,
116 std::u16string_view rType
,
119 css::uno::Sequence
< css::beans::PropertyValue
>& rArgs
)
121 SaveResult
eRet( SAVE_ERROR
);
125 uno::Sequence
< beans::PropertyValue
> aProps
;
126 css::uno::Reference
< css::container::XNameAccess
> xFilterCFG(
127 xSMGR
->createInstance( u
"com.sun.star.document.FilterFactory"_ustr
), uno::UNO_QUERY
);
128 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
130 if ( !xFilterCFG
.is() )
133 uno::Any aAny
= xFilterCFG
->getByName( rFilterName
);
135 if ( aAny
>>= aProps
)
137 for (const auto& rProp
: aProps
)
139 if( rProp
.Name
== "UIComponent" )
141 OUString aServiceName
;
142 rProp
.Value
>>= aServiceName
;
143 if( !aServiceName
.isEmpty() )
145 uno::Reference
< ui::dialogs::XExecutableDialog
> xFilterDialog(
146 xSMGR
->createInstance( aServiceName
), uno::UNO_QUERY
);
147 uno::Reference
< beans::XPropertyAccess
> xFilterProperties(
148 xFilterDialog
, uno::UNO_QUERY
);
150 if( xFilterDialog
.is() && xFilterProperties
.is() )
152 uno::Reference
< document::XExporter
> xExporter( xFilterDialog
, uno::UNO_QUERY
);
154 if ( rType
== PDF_DOCUMENT_TYPE
)
156 //add an internal property, used to tell the dialog we want to set a different
157 //string for the ok button
158 //used in filter/source/pdf/impdialog.cxx
159 uno::Sequence
< beans::PropertyValue
> aFilterDataValue
{
160 comphelper::makePropertyValue(u
"_OkButtonString"_ustr
,
161 SfxResId(STR_PDF_EXPORT_SEND
))
164 //add to the filterdata property, the only one the PDF export filter dialog will care for
165 uno::Sequence
< beans::PropertyValue
> aPropsForDialog
{
166 comphelper::makePropertyValue(u
"FilterData"_ustr
, aFilterDataValue
)
169 //when executing the dialog will merge the persistent FilterData properties
170 xFilterProperties
->setPropertyValues( aPropsForDialog
);
174 xExporter
->setSourceDocument( xModel
);
176 if( xFilterDialog
->execute() )
178 //get the filter data
179 const uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
= xFilterProperties
->getPropertyValues();
181 //add them to the args
182 auto pProp
= std::find_if(aPropsFromDialog
.begin(), aPropsFromDialog
.end(),
183 [](const beans::PropertyValue
& rDialogProp
) { return rDialogProp
.Name
== "FilterData"; });
184 if (pProp
!= aPropsFromDialog
.end())
186 //found the filterdata, add to the storing argument
187 rArgs
.realloc( ++rNumArgs
);
188 auto pArgs
= rArgs
.getArray();
189 pArgs
[rNumArgs
-1].Name
= pProp
->Name
;
190 pArgs
[rNumArgs
-1].Value
= pProp
->Value
;
192 eRet
= SAVE_SUCCESSFUL
;
196 // cancel from dialog, then do not send
197 // If the model is not modified, it could be modified by the dispatch calls.
198 // Therefore set back to modified = false. This should not hurt if we call
199 // on a non-modified model.
204 xModifiable
->setModified( false );
206 catch( css::beans::PropertyVetoException
& )
210 eRet
= SAVE_CANCELLED
;
219 catch( css::uno::RuntimeException
& )
223 catch( uno::Exception
& )
230 bool SfxMailModel::IsEmpty() const
232 return maAttachedDocuments
.empty();
235 SfxMailModel::SaveResult
SfxMailModel::SaveDocumentAsFormat(
236 const OUString
& aSaveFileName
,
237 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
238 const OUString
& rType
,
239 OUString
& rFileNamePath
)
241 SaveResult
eRet( SAVE_ERROR
);
242 bool bSendAsPDF
= ( rType
== PDF_DOCUMENT_TYPE
);
244 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
245 const css::uno::Reference
< css::uno::XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
249 css::uno::Reference
< css::frame::XModuleManager2
> xModuleManager( css::frame::ModuleManager::create(xContext
) );
254 aModule
= xModuleManager
->identify( xFrameOrModel
);
256 catch ( css::uno::RuntimeException
& )
260 catch ( css::uno::Exception
& )
264 css::uno::Reference
< css::frame::XFrame
> xFrame( xFrameOrModel
, css::uno::UNO_QUERY
);
265 css::uno::Reference
< css::frame::XModel
> xModel( xFrameOrModel
, css::uno::UNO_QUERY
);
268 css::uno::Reference
< css::frame::XController
> xController
= xFrame
->getController();
269 if ( xController
.is() )
270 xModel
= xController
->getModel();
273 // We need at least a valid module name and model reference
274 if ( !aModule
.isEmpty() && xModel
.is() )
276 bool bModified( false );
277 bool bHasLocation( false );
278 bool bStoreTo( false );
280 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
281 css::uno::Reference
< css::frame::XStorable
> xStorable( xModel
, css::uno::UNO_QUERY
);
283 if ( xModifiable
.is() )
284 bModified
= xModifiable
->isModified();
285 if ( xStorable
.is() )
287 OUString aLocation
= xStorable
->getLocation();
288 INetURLObject
aFileObj( aLocation
);
290 bool bPrivateProtocol
= ( aFileObj
.GetProtocol() == INetProtocol::PrivSoffice
);
292 bHasLocation
= !aLocation
.isEmpty() && !bPrivateProtocol
;
293 OSL_ASSERT( !bPrivateProtocol
);
295 if ( !rType
.isEmpty() )
298 if ( xStorable
.is() )
300 OUString aFilterName
;
301 OUString
aTypeName( rType
);
305 css::uno::Reference
< css::container::XContainerQuery
> xContainerQuery(
306 xSMGR
->createInstance( u
"com.sun.star.document.FilterFactory"_ustr
),
307 css::uno::UNO_QUERY
);
311 // Retrieve filter from type
312 css::uno::Sequence
< css::beans::NamedValue
> aQuery( bSendAsPDF
? 3 : 2 );
313 auto pQuery
= aQuery
.getArray();
314 pQuery
[0].Name
= "Type";
315 pQuery
[0].Value
<<= aTypeName
;
316 pQuery
[1].Name
= "DocumentService";
317 pQuery
[1].Value
<<= aModule
;
321 // FIXME: we want just an export filter. However currently we need
322 // exact flag value as detailed in the filter configuration to get it
323 // this seems to be a bug
324 // without flags we get an import filter here, which is also unwanted
325 pQuery
[2].Name
= "Flags";
326 pQuery
[2].Value
<<= sal_Int32(0x80042); // SfxFilterFlags: EXPORT ALIEN 3RDPARTY
329 css::uno::Reference
< css::container::XEnumeration
> xEnumeration
=
330 xContainerQuery
->createSubSetEnumerationByProperties( aQuery
);
332 if ( xEnumeration
->hasMoreElements() )
334 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xEnumeration
->nextElement() );
335 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
342 // Retrieve filter from media descriptor
343 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
344 OUString aOrgFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
347 if ( aOrgFilterName
== aFilterName
)
349 // We should save the document in the original format. Therefore this
350 // is not a storeTo operation. To support signing in this case, reset
360 // Retrieve filter from media descriptor
361 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
362 aFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
367 if ( !bHasLocation
|| aFilterName
.isEmpty())
369 // Retrieve the user defined default filter
372 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xModuleManager
->getByName( aModule
) );
373 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
374 u
"ooSetupFactoryDefaultFilter"_ustr
,
376 css::uno::Reference
< css::container::XNameAccess
> xNameAccess(
377 xContainerQuery
, css::uno::UNO_QUERY
);
378 if ( xNameAccess
.is() )
380 ::comphelper::SequenceAsHashMap
aFilterPropsHM2( xNameAccess
->getByName( aFilterName
) );
381 aTypeName
= aFilterPropsHM2
.getUnpackedValueOrDefault(
386 catch ( css::container::NoSuchElementException
& )
389 catch ( css::beans::UnknownPropertyException
& )
395 // No filter found => error
396 // No type and no location => error
397 if (( aFilterName
.isEmpty() ) ||
398 ( aTypeName
.isEmpty() && !bHasLocation
))
401 // Determine file name and extension
402 if ( bHasLocation
&& !bStoreTo
)
404 INetURLObject
aFileObj( xStorable
->getLocation() );
405 aExtension
= aFileObj
.getExtension();
409 css::uno::Reference
< container::XNameAccess
> xTypeDetection(
410 xSMGR
->createInstance( u
"com.sun.star.document.TypeDetection"_ustr
),
411 css::uno::UNO_QUERY
);
414 if ( xTypeDetection
.is() )
418 ::comphelper::SequenceAsHashMap
aTypeNamePropsHM( xTypeDetection
->getByName( aTypeName
) );
419 uno::Sequence
< OUString
> aExtensions
= aTypeNamePropsHM
.getUnpackedValueOrDefault(
421 ::uno::Sequence
< OUString
>() );
422 if ( aExtensions
.hasElements() )
423 aExtension
= aExtensions
[0];
425 catch ( css::container::NoSuchElementException
& )
431 // Use provided save file name. If empty determine file name
432 aFileName
= aSaveFileName
;
433 if ( aFileName
.isEmpty() )
437 // Create a noname file name with the correct extension
438 aFileName
= "noname";
442 // Determine file name from model
443 INetURLObject
aFileObj( xStorable
->getLocation() );
444 aFileName
= aFileObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DecodeMechanism::NONE
);
448 // No file name => error
449 if ( aFileName
.isEmpty() )
452 OSL_ASSERT( !aFilterName
.isEmpty() );
453 OSL_ASSERT( !aFileName
.isEmpty() );
455 // Creates a temporary directory to store a predefined file into it.
456 // This makes it possible to store the file for "send document as e-mail"
457 // with the original file name. We cannot use the original file as
458 // some mail programs need exclusive access.
459 INetURLObject
aFilePathObj( ::utl::CreateTempURL(nullptr, true) );
460 aFilePathObj
.insertName( aFileName
);
461 aFilePathObj
.setExtension( aExtension
);
463 OUString aFileURL
= aFilePathObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
465 sal_Int32
nNumArgs(1);
466 static constexpr OUString
aPasswordPropName( u
"Password"_ustr
);
467 css::uno::Sequence
< css::beans::PropertyValue
> aArgs
{ comphelper::makePropertyValue(
468 u
"FilterName"_ustr
, aFilterName
) };
470 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
471 OUString aPassword
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
474 if ( !aPassword
.isEmpty() )
476 aArgs
.realloc( ++nNumArgs
);
477 auto pArgs
= aArgs
.getArray();
478 pArgs
[nNumArgs
-1].Name
= aPasswordPropName
;
479 pArgs
[nNumArgs
-1].Value
<<= aPassword
;
482 bool bNeedsPreparation
= false;
483 css::util::URL aPrepareURL
;
484 css::uno::Reference
< css::frame::XDispatch
> xPrepareDispatch
;
485 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatchProvider( xFrame
, css::uno::UNO_QUERY
);
486 css::uno::Reference
< css::util::XURLTransformer
> xURLTransformer( css::util::URLTransformer::create( xContext
) );
491 // check if the document needs to be prepared for sending as mail (embedding of links, removal of invisible content)
493 aPrepareURL
.Complete
= ".uno:PrepareMailExport";
494 xURLTransformer
->parseStrict( aPrepareURL
);
496 if ( xDispatchProvider
.is() )
498 xPrepareDispatch
.set( xDispatchProvider
->queryDispatch( aPrepareURL
, OUString(), 0 ));
499 if ( xPrepareDispatch
.is() )
501 rtl::Reference
<PrepareListener_Impl
> pPrepareListener
= new PrepareListener_Impl
;
502 xPrepareDispatch
->addStatusListener( pPrepareListener
, aPrepareURL
);
503 bNeedsPreparation
= pPrepareListener
->IsSet();
504 xPrepareDispatch
->removeStatusListener( pPrepareListener
, aPrepareURL
);
508 catch ( css::uno::RuntimeException
& )
512 catch ( css::uno::Exception
& )
517 if ( bModified
|| !bHasLocation
|| bStoreTo
|| bNeedsPreparation
)
519 // Document is modified, is newly created or should be stored in a special format
522 if( bNeedsPreparation
&& xPrepareDispatch
.is() )
526 css::uno::Sequence
< css::beans::PropertyValue
> aDispatchArgs
;
527 xPrepareDispatch
->dispatch( aPrepareURL
, aDispatchArgs
);
529 catch ( css::uno::RuntimeException
& )
533 catch ( css::uno::Exception
& )
538 //check if this is the pdf output filter (i#64555)
541 SaveResult eShowPDFFilterDialog
= ShowFilterOptionsDialog(
542 xSMGR
, xModel
, aFilterName
, rType
, bModified
, nNumArgs
, aArgs
);
544 // don't continue on dialog cancel or error
545 if ( eShowPDFFilterDialog
!= SAVE_SUCCESSFUL
)
546 return eShowPDFFilterDialog
;
549 xStorable
->storeToURL( aFileURL
, aArgs
);
550 rFileNamePath
= aFileURL
;
551 eRet
= SAVE_SUCCESSFUL
;
556 // #i30432# notify that export is finished - the Writer may want to restore removed content
557 aURL
.Complete
= ".uno:MailExportFinished";
558 xURLTransformer
->parseStrict( aURL
);
560 if ( xDispatchProvider
.is() )
562 css::uno::Reference
< css::frame::XDispatch
> xDispatch(
563 xDispatchProvider
->queryDispatch( aURL
, OUString(), 0 ));
564 if ( xDispatch
.is() )
568 css::uno::Sequence
< css::beans::PropertyValue
> aDispatchArgs
;
569 xDispatch
->dispatch( aURL
, aDispatchArgs
);
571 catch ( css::uno::RuntimeException
& )
575 catch ( css::uno::Exception
& )
581 // If the model is not modified, it could be modified by the dispatch calls.
582 // Therefore set back to modified = false. This should not hurt if we call
583 // on a non-modified model.
588 xModifiable
->setModified( false );
590 catch( css::beans::PropertyVetoException
& )
595 catch ( css::io::IOException
& )
602 // We need 1:1 copy of the document to preserve an added signature.
603 aArgs
.realloc( ++nNumArgs
);
604 auto pArgs
= aArgs
.getArray();
605 pArgs
[nNumArgs
-1].Name
= "CopyStreamIfPossible";
606 pArgs
[nNumArgs
-1].Value
<<= true;
610 xStorable
->storeToURL( aFileURL
, aArgs
);
611 rFileNamePath
= aFileURL
;
612 eRet
= SAVE_SUCCESSFUL
;
614 catch ( css::io::IOException
& )
625 SfxMailModel::SfxMailModel()
629 SfxMailModel::~SfxMailModel()
633 void SfxMailModel::AddToAddress( const OUString
& rAddress
)
635 // don't add an empty address
636 if ( !rAddress
.isEmpty() )
640 mpToList
.reset(new AddressList_Impl
);
642 // add address to list
643 mpToList
->push_back( rAddress
);
647 SfxMailModel::SendMailResult
SfxMailModel::AttachDocument(
648 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
649 const OUString
& sAttachmentTitle
)
653 SaveResult eSaveResult
= SaveDocumentAsFormat( sAttachmentTitle
, xFrameOrModel
, OUString()/*sDocumentType*/, sFileName
);
654 if ( eSaveResult
== SAVE_SUCCESSFUL
&& !sFileName
.isEmpty() )
655 maAttachedDocuments
.push_back(sFileName
);
656 return eSaveResult
== SAVE_SUCCESSFUL
? SEND_MAIL_OK
: SEND_MAIL_ERROR
;
659 SfxMailModel::SendMailResult
SfxMailModel::Send( const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
661 OSL_ENSURE(!maAttachedDocuments
.empty(),"No document added!");
662 SendMailResult eResult
= SEND_MAIL_ERROR
;
663 if ( !maAttachedDocuments
.empty() )
665 const css::uno::Reference
< XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
667 css::uno::Reference
< XSimpleMailClientSupplier
> xSimpleMailClientSupplier
;
669 // Prefer the SimpleSystemMail service if available
671 xSimpleMailClientSupplier
= SimpleSystemMail::create( xContext
);
673 catch ( const uno::Exception
& )
676 if ( ! xSimpleMailClientSupplier
.is() )
679 xSimpleMailClientSupplier
= SimpleCommandMail::create( xContext
);
681 catch ( const uno::Exception
& )
685 if ( xSimpleMailClientSupplier
.is() )
687 css::uno::Reference
< XSimpleMailClient
> xSimpleMailClient
= xSimpleMailClientSupplier
->querySimpleMailClient();
689 if ( !xSimpleMailClient
.is() )
691 // no mail client support => message box!
692 return SEND_MAIL_ERROR
;
695 // we have a simple mail client
696 css::uno::Reference
< XSimpleMailMessage
> xSimpleMailMessage
= xSimpleMailClient
->createSimpleMailMessage();
697 if ( xSimpleMailMessage
.is() )
699 sal_Int32 nSendFlags
= SimpleMailClientFlags::DEFAULTS
;
700 if ( maFromAddress
.isEmpty() )
702 // from address not set, try figure out users e-mail address
703 CreateFromAddress_Impl( maFromAddress
);
705 xSimpleMailMessage
->setOriginator( maFromAddress
);
707 size_t nToCount
= mpToList
? mpToList
->size() : 0;
709 // set recipient (only one) for this simple mail server!!
712 xSimpleMailMessage
->setRecipient( mpToList
->at( 0 ) );
713 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
716 // all other recipient must be handled with CC recipients!
719 Sequence
< OUString
> aCcRecipientSeq( nToCount
- 1 );
720 std::copy_n(std::next(mpToList
->begin()), aCcRecipientSeq
.getLength(),
721 aCcRecipientSeq
.getArray());
722 xSimpleMailMessage
->setCcRecipient( aCcRecipientSeq
);
725 Sequence
< OUString
> aAttachmentSeq(maAttachedDocuments
.data(),maAttachedDocuments
.size());
727 if ( xSimpleMailMessage
->getSubject().isEmpty() ) {
729 maAttachedDocuments
[0], INetURLObject::EncodeMechanism::WasEncoded
);
732 INetURLObject::LAST_SEGMENT
, false,
733 INetURLObject::DecodeMechanism::WithCharset
));
734 if (subject
.isEmpty()) {
735 subject
= maAttachedDocuments
[0];
737 if ( maAttachedDocuments
.size() > 1 )
739 xSimpleMailMessage
->setSubject( subject
);
741 xSimpleMailMessage
->setAttachement( aAttachmentSeq
);
746 xSimpleMailClient
->sendSimpleMailMessage( xSimpleMailMessage
, nSendFlags
);
749 catch ( IllegalArgumentException
& )
758 css::uno::Reference
< css::awt::XWindow
> xParentWindow
= xFrame
->getContainerWindow();
760 SolarMutexGuard aGuard
;
762 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(Application::GetFrameWeld(xParentWindow
), u
"sfx/ui/errorfindemaildialog.ui"_ustr
));
763 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog(u
"ErrorFindEmailDialog"_ustr
));
765 eResult
= SEND_MAIL_CANCELLED
;
768 eResult
= SEND_MAIL_OK
;
773 eResult
= SEND_MAIL_CANCELLED
;
778 SfxMailModel::SendMailResult
SfxMailModel::SaveAndSend( const css::uno::Reference
< css::frame::XFrame
>& xFrame
, const OUString
& rTypeName
)
780 SaveResult eSaveResult
;
781 SendMailResult eResult
= SEND_MAIL_ERROR
;
784 eSaveResult
= SaveDocumentAsFormat( OUString(), xFrame
, rTypeName
, aFileName
);
786 if ( eSaveResult
== SAVE_SUCCESSFUL
)
788 maAttachedDocuments
.push_back( aFileName
);
789 return Send( xFrame
);
791 else if ( eSaveResult
== SAVE_CANCELLED
)
792 eResult
= SEND_MAIL_CANCELLED
;
797 // functions -------------------------------------------------------------
799 bool CreateFromAddress_Impl( OUString
& rFrom
)
803 This function tries to create a From-address with the help of IniManagers.
804 For this the fields 'first name', 'Name' and 'Email' are read from the
805 application-ini-data. If these fields are not set, FALSE is returned.
809 sal_True: Address could be created.
810 sal_False: Address could not be created.
814 SvtUserOptions aUserCFG
;
815 OUString aName
= aUserCFG
.GetLastName ();
816 OUString aFirstName
= aUserCFG
.GetFirstName ();
817 if ( !aFirstName
.isEmpty() || !aName
.isEmpty() )
819 if ( !aFirstName
.isEmpty() )
821 rFrom
= comphelper::string::strip(aFirstName
, ' ');
823 if ( !aName
.isEmpty() )
826 rFrom
+= comphelper::string::strip(aName
, ' ');
827 // remove illegal characters
828 rFrom
= rFrom
.replaceAll("<", "").replaceAll(">", "").replaceAll("@", "");
830 OUString aEmailName
= aUserCFG
.GetEmail();
832 // remove illegal characters
833 aEmailName
= aEmailName
.replaceAll("<", "").replaceAll(">", "");
835 if ( !aEmailName
.isEmpty() )
837 if ( !rFrom
.isEmpty() )
839 rFrom
+= "<" + comphelper::string::strip(aEmailName
, ' ') + ">";
843 return !rFrom
.isEmpty();
846 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */