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/sequenceashashmap.hxx>
56 #include <comphelper/string.hxx>
57 #include <vcl/svapp.hxx>
58 #include <cppuhelper/implbase.hxx>
61 using namespace ::com::sun::star
;
62 using namespace ::com::sun::star::beans
;
63 using namespace ::com::sun::star::frame
;
64 using namespace ::com::sun::star::io
;
65 using namespace ::com::sun::star::lang
;
66 using namespace ::com::sun::star::ucb
;
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 char PDF_DOCUMENT_TYPE
[] = "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 const OUString
& 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( "com.sun.star.document.FilterFactory" ), 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
: std::as_const(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::Sequence
< beans::PropertyValue
> aPropsForDialog(1);
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(1);
161 aFilterDataValue
[0].Name
= "_OkButtonString";
162 aFilterDataValue
[0].Value
<<= SfxResId(STR_PDF_EXPORT_SEND
);
164 //add to the filterdata property, the only one the PDF export filter dialog will care for
165 aPropsForDialog
[0].Name
= "FilterData";
166 aPropsForDialog
[0].Value
<<= aFilterDataValue
;
168 //when executing the dialog will merge the persistent FilterData properties
169 xFilterProperties
->setPropertyValues( aPropsForDialog
);
173 xExporter
->setSourceDocument( xModel
);
175 if( xFilterDialog
->execute() )
177 //get the filter data
178 uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
= xFilterProperties
->getPropertyValues();
180 //add them to the args
181 auto pProp
= std::find_if(aPropsFromDialog
.begin(), aPropsFromDialog
.end(),
182 [](const beans::PropertyValue
& rDialogProp
) { return rDialogProp
.Name
== "FilterData"; });
183 if (pProp
!= aPropsFromDialog
.end())
185 //found the filterdata, add to the storing argument
186 rArgs
.realloc( ++rNumArgs
);
187 rArgs
[rNumArgs
-1].Name
= pProp
->Name
;
188 rArgs
[rNumArgs
-1].Value
= pProp
->Value
;
190 eRet
= SAVE_SUCCESSFULL
;
194 // cancel from dialog, then do not send
195 // If the model is not modified, it could be modified by the dispatch calls.
196 // Therefore set back to modified = false. This should not hurt if we call
197 // on a non-modified model.
202 xModifiable
->setModified( false );
204 catch( css::beans::PropertyVetoException
& )
208 eRet
= SAVE_CANCELLED
;
217 catch( css::uno::RuntimeException
& )
221 catch( uno::Exception
& )
228 bool SfxMailModel::IsEmpty() const
230 return maAttachedDocuments
.empty();
233 SfxMailModel::SaveResult
SfxMailModel::SaveDocumentAsFormat(
234 const OUString
& aSaveFileName
,
235 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
236 const OUString
& rType
,
237 OUString
& rFileNamePath
)
239 SaveResult
eRet( SAVE_ERROR
);
240 bool bSendAsPDF
= ( rType
== PDF_DOCUMENT_TYPE
);
242 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
243 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
247 css::uno::Reference
< css::frame::XModuleManager2
> xModuleManager( css::frame::ModuleManager::create(xContext
) );
252 aModule
= xModuleManager
->identify( xFrameOrModel
);
254 catch ( css::uno::RuntimeException
& )
258 catch ( css::uno::Exception
& )
262 css::uno::Reference
< css::frame::XFrame
> xFrame( xFrameOrModel
, css::uno::UNO_QUERY
);
263 css::uno::Reference
< css::frame::XModel
> xModel( xFrameOrModel
, css::uno::UNO_QUERY
);
266 css::uno::Reference
< css::frame::XController
> xController
= xFrame
->getController();
267 if ( xController
.is() )
268 xModel
= xController
->getModel();
271 // We need at least a valid module name and model reference
272 if ( !aModule
.isEmpty() && xModel
.is() )
274 bool bModified( false );
275 bool bHasLocation( false );
276 bool bStoreTo( false );
278 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
279 css::uno::Reference
< css::frame::XStorable
> xStorable( xModel
, css::uno::UNO_QUERY
);
281 if ( xModifiable
.is() )
282 bModified
= xModifiable
->isModified();
283 if ( xStorable
.is() )
285 OUString aLocation
= xStorable
->getLocation();
286 INetURLObject
aFileObj( aLocation
);
288 bool bPrivateProtocol
= ( aFileObj
.GetProtocol() == INetProtocol::PrivSoffice
);
290 bHasLocation
= !aLocation
.isEmpty() && !bPrivateProtocol
;
291 OSL_ASSERT( !bPrivateProtocol
);
293 if ( !rType
.isEmpty() )
296 if ( xStorable
.is() )
298 OUString aFilterName
;
299 OUString
aTypeName( rType
);
303 css::uno::Reference
< css::container::XContainerQuery
> xContainerQuery(
304 xSMGR
->createInstance( "com.sun.star.document.FilterFactory" ),
305 css::uno::UNO_QUERY
);
309 // Retrieve filter from type
310 css::uno::Sequence
< css::beans::NamedValue
> aQuery( bSendAsPDF
? 3 : 2 );
311 aQuery
[0].Name
= "Type";
312 aQuery
[0].Value
<<= aTypeName
;
313 aQuery
[1].Name
= "DocumentService";
314 aQuery
[1].Value
<<= aModule
;
318 // FIXME: we want just an export filter. However currently we need
319 // exact flag value as detailed in the filter configuration to get it
320 // this seems to be a bug
321 // without flags we get an import filter here, which is also unwanted
322 aQuery
[2].Name
= "Flags";
323 aQuery
[2].Value
<<= sal_Int32(0x80042); // EXPORT ALIEN 3RDPARTY
326 css::uno::Reference
< css::container::XEnumeration
> xEnumeration
=
327 xContainerQuery
->createSubSetEnumerationByProperties( aQuery
);
329 if ( xEnumeration
->hasMoreElements() )
331 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xEnumeration
->nextElement() );
332 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
339 // Retrieve filter from media descriptor
340 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
341 OUString aOrgFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
344 if ( aOrgFilterName
== aFilterName
)
346 // We should save the document in the original format. Therefore this
347 // is not a storeTo operation. To support signing in this case, reset
357 // Retrieve filter from media descriptor
358 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
359 aFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
364 if ( !bHasLocation
|| aFilterName
.isEmpty())
366 // Retrieve the user defined default filter
369 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xModuleManager
->getByName( aModule
) );
370 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
371 "ooSetupFactoryDefaultFilter",
373 css::uno::Reference
< css::container::XNameAccess
> xNameAccess(
374 xContainerQuery
, css::uno::UNO_QUERY
);
375 if ( xNameAccess
.is() )
377 ::comphelper::SequenceAsHashMap
aFilterPropsHM2( xNameAccess
->getByName( aFilterName
) );
378 aTypeName
= aFilterPropsHM2
.getUnpackedValueOrDefault(
383 catch ( css::container::NoSuchElementException
& )
386 catch ( css::beans::UnknownPropertyException
& )
392 // No filter found => error
393 // No type and no location => error
394 if (( aFilterName
.isEmpty() ) ||
395 ( aTypeName
.isEmpty() && !bHasLocation
))
398 // Determine file name and extension
399 if ( bHasLocation
&& !bStoreTo
)
401 INetURLObject
aFileObj( xStorable
->getLocation() );
402 aExtension
= aFileObj
.getExtension();
406 css::uno::Reference
< container::XNameAccess
> xTypeDetection(
407 xSMGR
->createInstance( "com.sun.star.document.TypeDetection" ),
408 css::uno::UNO_QUERY
);
411 if ( xTypeDetection
.is() )
415 ::comphelper::SequenceAsHashMap
aTypeNamePropsHM( xTypeDetection
->getByName( aTypeName
) );
416 uno::Sequence
< OUString
> aExtensions
= aTypeNamePropsHM
.getUnpackedValueOrDefault(
418 ::uno::Sequence
< OUString
>() );
419 if ( aExtensions
.hasElements() )
420 aExtension
= aExtensions
[0];
422 catch ( css::container::NoSuchElementException
& )
428 // Use provided save file name. If empty determine file name
429 aFileName
= aSaveFileName
;
430 if ( aFileName
.isEmpty() )
434 // Create a noname file name with the correct extension
435 aFileName
= "noname";
439 // Determine file name from model
440 INetURLObject
aFileObj( xStorable
->getLocation() );
441 aFileName
= aFileObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DecodeMechanism::NONE
);
445 // No file name => error
446 if ( aFileName
.isEmpty() )
449 OSL_ASSERT( !aFilterName
.isEmpty() );
450 OSL_ASSERT( !aFileName
.isEmpty() );
452 // Creates a temporary directory to store a predefined file into it.
453 // This makes it possible to store the file for "send document as e-mail"
454 // with the original file name. We cannot use the original file as
455 // some mail programs need exclusive access.
456 ::utl::TempFile
aTempDir( nullptr, true );
458 INetURLObject
aFilePathObj( aTempDir
.GetURL() );
459 aFilePathObj
.insertName( aFileName
);
460 aFilePathObj
.setExtension( aExtension
);
462 OUString aFileURL
= aFilePathObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
464 sal_Int32
nNumArgs(0);
465 const OUString
aPasswordPropName( "Password" );
466 css::uno::Sequence
< css::beans::PropertyValue
> aArgs( ++nNumArgs
);
467 aArgs
[nNumArgs
-1].Name
= "FilterName";
468 aArgs
[nNumArgs
-1].Value
<<= aFilterName
;
470 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
471 OUString aPassword
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
474 if ( !aPassword
.isEmpty() )
476 aArgs
.realloc( ++nNumArgs
);
477 aArgs
[nNumArgs
-1].Name
= aPasswordPropName
;
478 aArgs
[nNumArgs
-1].Value
<<= aPassword
;
481 bool bNeedsPreparation
= false;
482 css::util::URL aPrepareURL
;
483 css::uno::Reference
< css::frame::XDispatch
> xPrepareDispatch
;
484 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatchProvider( xFrame
, css::uno::UNO_QUERY
);
485 css::uno::Reference
< css::util::XURLTransformer
> xURLTransformer( css::util::URLTransformer::create( xContext
) );
490 // check if the document needs to be prepared for sending as mail (embedding of links, removal of invisible content)
492 aPrepareURL
.Complete
= ".uno:PrepareMailExport";
493 xURLTransformer
->parseStrict( aPrepareURL
);
495 if ( xDispatchProvider
.is() )
497 xPrepareDispatch
.set( xDispatchProvider
->queryDispatch( aPrepareURL
, OUString(), 0 ));
498 if ( xPrepareDispatch
.is() )
500 PrepareListener_Impl
* pPrepareListener
= new PrepareListener_Impl
;
501 uno::Reference
< css::frame::XStatusListener
> xStatusListener
= pPrepareListener
;
502 xPrepareDispatch
->addStatusListener( xStatusListener
, aPrepareURL
);
503 bNeedsPreparation
= pPrepareListener
->IsSet();
504 xPrepareDispatch
->removeStatusListener( xStatusListener
, 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_SUCCESSFULL
)
546 return eShowPDFFilterDialog
;
549 xStorable
->storeToURL( aFileURL
, aArgs
);
550 rFileNamePath
= aFileURL
;
551 eRet
= SAVE_SUCCESSFULL
;
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 aArgs
[nNumArgs
-1].Name
= "CopyStreamIfPossible";
605 aArgs
[nNumArgs
-1].Value
<<= true;
609 xStorable
->storeToURL( aFileURL
, aArgs
);
610 rFileNamePath
= aFileURL
;
611 eRet
= SAVE_SUCCESSFULL
;
613 catch ( css::io::IOException
& )
624 SfxMailModel::SfxMailModel()
628 SfxMailModel::~SfxMailModel()
632 void SfxMailModel::AddToAddress( const OUString
& rAddress
)
634 // don't add an empty address
635 if ( !rAddress
.isEmpty() )
639 mpToList
.reset(new AddressList_Impl
);
641 // add address to list
642 mpToList
->push_back( rAddress
);
646 SfxMailModel::SendMailResult
SfxMailModel::AttachDocument(
647 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
648 const OUString
& sAttachmentTitle
)
652 SaveResult eSaveResult
= SaveDocumentAsFormat( sAttachmentTitle
, xFrameOrModel
, OUString()/*sDocumentType*/, sFileName
);
653 if ( eSaveResult
== SAVE_SUCCESSFULL
&& !sFileName
.isEmpty() )
654 maAttachedDocuments
.push_back(sFileName
);
655 return eSaveResult
== SAVE_SUCCESSFULL
? SEND_MAIL_OK
: SEND_MAIL_ERROR
;
658 SfxMailModel::SendMailResult
SfxMailModel::Send( const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
660 OSL_ENSURE(!maAttachedDocuments
.empty(),"No document added!");
661 SendMailResult eResult
= SEND_MAIL_ERROR
;
662 if ( !maAttachedDocuments
.empty() )
664 css::uno::Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
666 css::uno::Reference
< XSimpleMailClientSupplier
> xSimpleMailClientSupplier
;
668 // Prefer the SimpleSystemMail service if available
670 xSimpleMailClientSupplier
= SimpleSystemMail::create( xContext
);
672 catch ( const uno::Exception
& )
675 if ( ! xSimpleMailClientSupplier
.is() )
678 xSimpleMailClientSupplier
= SimpleCommandMail::create( xContext
);
680 catch ( const uno::Exception
& )
684 if ( xSimpleMailClientSupplier
.is() )
686 css::uno::Reference
< XSimpleMailClient
> xSimpleMailClient
= xSimpleMailClientSupplier
->querySimpleMailClient();
688 if ( !xSimpleMailClient
.is() )
690 // no mail client support => message box!
691 return SEND_MAIL_ERROR
;
694 // we have a simple mail client
695 css::uno::Reference
< XSimpleMailMessage
> xSimpleMailMessage
= xSimpleMailClient
->createSimpleMailMessage();
696 if ( xSimpleMailMessage
.is() )
698 sal_Int32 nSendFlags
= SimpleMailClientFlags::DEFAULTS
;
699 if ( maFromAddress
.isEmpty() )
701 // from address not set, try figure out users e-mail address
702 CreateFromAddress_Impl( maFromAddress
);
704 xSimpleMailMessage
->setOriginator( maFromAddress
);
706 size_t nToCount
= mpToList
? mpToList
->size() : 0;
708 // set recipient (only one) for this simple mail server!!
711 xSimpleMailMessage
->setRecipient( mpToList
->at( 0 ) );
712 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
715 // all other recipient must be handled with CC recipients!
718 Sequence
< OUString
> aCcRecipientSeq( nToCount
- 1 );
719 for ( size_t i
= 1; i
< nToCount
; ++i
)
720 aCcRecipientSeq
[i
- 1] = mpToList
->at(i
);
721 xSimpleMailMessage
->setCcRecipient( aCcRecipientSeq
);
724 Sequence
< OUString
> aAttachmentSeq(maAttachedDocuments
.data(),maAttachedDocuments
.size());
726 if ( xSimpleMailMessage
->getSubject().isEmpty() ) {
728 maAttachedDocuments
[0], INetURLObject::EncodeMechanism::WasEncoded
);
731 INetURLObject::LAST_SEGMENT
, false,
732 INetURLObject::DecodeMechanism::WithCharset
));
733 if (subject
.isEmpty()) {
734 subject
= maAttachedDocuments
[0];
736 if ( maAttachedDocuments
.size() > 1 )
738 xSimpleMailMessage
->setSubject( subject
);
740 xSimpleMailMessage
->setAttachement( aAttachmentSeq
);
745 xSimpleMailClient
->sendSimpleMailMessage( xSimpleMailMessage
, nSendFlags
);
748 catch ( IllegalArgumentException
& )
757 css::uno::Reference
< css::awt::XWindow
> xParentWindow
= xFrame
->getContainerWindow();
759 SolarMutexGuard aGuard
;
761 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(Application::GetFrameWeld(xParentWindow
), "sfx/ui/errorfindemaildialog.ui"));
762 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("ErrorFindEmailDialog"));
764 eResult
= SEND_MAIL_CANCELLED
;
767 eResult
= SEND_MAIL_OK
;
772 eResult
= SEND_MAIL_CANCELLED
;
777 SfxMailModel::SendMailResult
SfxMailModel::SaveAndSend( const css::uno::Reference
< css::frame::XFrame
>& xFrame
, const OUString
& rTypeName
)
779 SaveResult eSaveResult
;
780 SendMailResult eResult
= SEND_MAIL_ERROR
;
783 eSaveResult
= SaveDocumentAsFormat( OUString(), xFrame
, rTypeName
, aFileName
);
785 if ( eSaveResult
== SAVE_SUCCESSFULL
)
787 maAttachedDocuments
.push_back( aFileName
);
788 return Send( xFrame
);
790 else if ( eSaveResult
== SAVE_CANCELLED
)
791 eResult
= SEND_MAIL_CANCELLED
;
796 // functions -------------------------------------------------------------
798 bool CreateFromAddress_Impl( OUString
& rFrom
)
802 This function tries to create a From-address with the help of IniManagers.
803 For this the fields 'first name', 'Name' and 'Email' are read from the
804 application-ini-data. If these fields are not set, FALSE is returned.
808 sal_True: Address could be created.
809 sal_False: Address could not be created.
813 SvtUserOptions aUserCFG
;
814 OUString aName
= aUserCFG
.GetLastName ();
815 OUString aFirstName
= aUserCFG
.GetFirstName ();
816 if ( !aFirstName
.isEmpty() || !aName
.isEmpty() )
818 if ( !aFirstName
.isEmpty() )
820 rFrom
= comphelper::string::strip(aFirstName
, ' ');
822 if ( !aName
.isEmpty() )
825 rFrom
+= comphelper::string::strip(aName
, ' ');
826 // remove illegal characters
827 rFrom
= rFrom
.replaceAll("<", "").replaceAll(">", "").replaceAll("@", "");
829 OUString aEmailName
= aUserCFG
.GetEmail();
831 // remove illegal characters
832 aEmailName
= aEmailName
.replaceAll("<", "").replaceAll(">", "");
834 if ( !aEmailName
.isEmpty() )
836 if ( !rFrom
.isEmpty() )
838 rFrom
+= "<" + comphelper::string::strip(aEmailName
, ' ') + ">";
842 return !rFrom
.isEmpty();
845 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */