nss: upgrade to release 3.73
[LibreOffice.git] / sfx2 / source / dialog / mailmodel.cxx
blob786d98e9398751894e939800b3186611d598109a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
71 namespace {
73 // - class PrepareListener_Impl ------------------------------------------
74 class PrepareListener_Impl : public ::cppu::WeakImplHelper< css::frame::XStatusListener >
76 bool m_bState;
77 public:
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() :
92 m_bState( false )
96 void PrepareListener_Impl::statusChanged(const css::frame::FeatureStateEvent& rEvent)
98 if( rEvent.IsEnabled )
99 rEvent.State >>= m_bState;
100 else
101 m_bState = false;
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,
117 bool bModified,
118 sal_Int32& rNumArgs,
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() )
131 return eRet;
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 );
172 if( xExporter.is() )
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;
192 else
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.
198 if ( !bModified )
202 xModifiable->setModified( false );
204 catch( css::beans::PropertyVetoException& )
208 eRet = SAVE_CANCELLED;
211 break;
217 catch( css::uno::RuntimeException& )
219 throw;
221 catch( uno::Exception& )
225 return eRet;
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();
244 if (!xContext.is())
245 return eRet;
247 css::uno::Reference< css::frame::XModuleManager2 > xModuleManager( css::frame::ModuleManager::create(xContext) );
249 OUString aModule;
252 aModule = xModuleManager->identify( xFrameOrModel );
254 catch ( css::uno::RuntimeException& )
256 throw;
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 );
264 if ( xFrame.is() )
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() )
294 bStoreTo = true;
296 if ( xStorable.is() )
298 OUString aFilterName;
299 OUString aTypeName( rType );
300 OUString aFileName;
301 OUString aExtension;
303 css::uno::Reference< css::container::XContainerQuery > xContainerQuery(
304 xSMGR->createInstance( "com.sun.star.document.FilterFactory" ),
305 css::uno::UNO_QUERY );
307 if ( bStoreTo )
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;
315 if( bSendAsPDF )
317 // #i91419#
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(
333 "Name",
334 OUString() );
337 if ( bHasLocation )
339 // Retrieve filter from media descriptor
340 ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() );
341 OUString aOrgFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault(
342 "FilterName",
343 OUString() );
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
348 // bStoreTo flag.
349 bStoreTo = false;
353 else
355 if ( bHasLocation )
357 // Retrieve filter from media descriptor
358 ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() );
359 aFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault(
360 "FilterName",
361 OUString() );
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",
372 OUString() );
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(
379 "Type",
380 OUString() );
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 ))
396 return eRet;
398 // Determine file name and extension
399 if ( bHasLocation && !bStoreTo )
401 INetURLObject aFileObj( xStorable->getLocation() );
402 aExtension = aFileObj.getExtension();
404 else
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(
417 "Extensions",
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() )
432 if ( !bHasLocation )
434 // Create a noname file name with the correct extension
435 aFileName = "noname";
437 else
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() )
447 return eRet;
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(
472 aPasswordPropName,
473 OUString() );
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 ) );
486 if( !bSendAsPDF )
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& )
510 throw;
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& )
531 throw;
533 catch ( css::uno::Exception& )
538 //check if this is the pdf output filter (i#64555)
539 if( bSendAsPDF )
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;
553 if( !bSendAsPDF )
555 css::util::URL aURL;
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& )
573 throw;
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.
584 if ( !bModified )
588 xModifiable->setModified( false );
590 catch( css::beans::PropertyVetoException& )
595 catch ( css::io::IOException& )
597 eRet = SAVE_ERROR;
600 else
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& )
615 eRet = SAVE_ERROR;
621 return eRet;
624 SfxMailModel::SfxMailModel()
628 SfxMailModel::~SfxMailModel()
632 void SfxMailModel::AddToAddress( const OUString& rAddress )
634 // don't add an empty address
635 if ( !rAddress.isEmpty() )
637 if ( !mpToList )
638 // create the list
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 )
650 OUString sFileName;
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
669 try {
670 xSimpleMailClientSupplier = SimpleSystemMail::create( xContext );
672 catch ( const uno::Exception & )
675 if ( ! xSimpleMailClientSupplier.is() )
677 try {
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!!
709 if ( nToCount >= 1 )
711 xSimpleMailMessage->setRecipient( mpToList->at( 0 ) );
712 nSendFlags = SimpleMailClientFlags::NO_USER_INTERFACE;
715 // all other recipient must be handled with CC recipients!
716 if ( nToCount > 1 )
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() ) {
727 INetURLObject url(
728 maAttachedDocuments[0], INetURLObject::EncodeMechanism::WasEncoded);
729 OUString subject(
730 url.getBase(
731 INetURLObject::LAST_SEGMENT, false,
732 INetURLObject::DecodeMechanism::WithCharset));
733 if (subject.isEmpty()) {
734 subject = maAttachedDocuments[0];
736 if ( maAttachedDocuments.size() > 1 )
737 subject += ", ...";
738 xSimpleMailMessage->setSubject( subject );
740 xSimpleMailMessage->setAttachement( aAttachmentSeq );
742 bool bSend( false );
745 xSimpleMailClient->sendSimpleMailMessage( xSimpleMailMessage, nSendFlags );
746 bSend = true;
748 catch ( IllegalArgumentException& )
751 catch ( Exception& )
755 if ( !bSend )
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"));
763 xBox->run();
764 eResult = SEND_MAIL_CANCELLED;
766 else
767 eResult = SEND_MAIL_OK;
771 else
772 eResult = SEND_MAIL_CANCELLED;
774 return eResult;
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;
781 OUString aFileName;
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;
793 return eResult;
796 // functions -------------------------------------------------------------
798 bool CreateFromAddress_Impl( OUString& rFrom )
800 /* [Description]
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.
806 [Return value]
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() )
823 rFrom += " ";
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() )
837 rFrom += " ";
838 rFrom += "<" + comphelper::string::strip(aEmailName, ' ') + ">";
840 else
841 rFrom.clear();
842 return !rFrom.isEmpty();
845 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */