LibreOffice Module shell (master) 1
cmdmailsuppl.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <config_folders.h>
21
22#include <osl/thread.h>
23
24#include <rtl/bootstrap.hxx>
25
26#include <osl/file.hxx>
27#include <rtl/strbuf.hxx>
28#include "cmdmailsuppl.hxx"
29#include "cmdmailmsg.hxx"
30#include <com/sun/star/system/SimpleMailClientFlags.hpp>
31#include <com/sun/star/container/XNameAccess.hpp>
32#include <com/sun/star/configuration/theDefaultProvider.hpp>
33#include <com/sun/star/beans/PropertyValue.hpp>
34#include <com/sun/star/uno/XComponentContext.hpp>
37
38using com::sun::star::beans::PropertyValue;
39using com::sun::star::system::XSimpleMailClientSupplier;
40using com::sun::star::system::XSimpleMailClient;
41using com::sun::star::system::XSimpleMailMessage;
42using com::sun::star::system::XSimpleMailMessage2;
43using com::sun::star::container::XNameAccess;
44using osl::FileBase;
45
46using namespace cppu;
47using namespace com::sun::star::system::SimpleMailClientFlags;
48using namespace com::sun::star::uno;
49using namespace com::sun::star::lang;
50using namespace com::sun::star::configuration;
51
53{
54 m_xConfigurationProvider = theDefaultProvider::get(xContext);
55}
56
57// XSimpleMailClientSupplier
58
60{
61 return static_cast < XSimpleMailClient * > (this);
62}
63
64// XSimpleMailClient
65
67{
69}
70
71namespace {
72
73void appendShellWord(OStringBuffer & buffer, OUString const & word, bool strict)
74{
75 OString sys;
76 if (!word.convertToString(
77 &sys, osl_getThreadTextEncoding(),
78 (strict
79 ? (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
80 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)
81 : OUSTRING_TO_OSTRING_CVTFLAGS)))
82 {
83 throw css::uno::Exception(
84 ("Could not convert \"" + word + "\" to encoding #"
85 + OUString::number(osl_getThreadTextEncoding())),
86 css::uno::Reference<css::uno::XInterface>());
87 }
88 buffer.append('\'');
89 for (sal_Int32 i = 0; i != sys.getLength(); ++i) {
90 char c = sys[i];
91 switch (c) {
92 case 0:
93 if (strict) {
94 throw css::uno::Exception(
95 "Could not convert word containing NUL, \"" + word + "\"",
96 css::uno::Reference<css::uno::XInterface>());
97 }
98 break;
99 case '\'':
100 buffer.append("'\\''");
101 break;
102 default:
103 buffer.append(c);
104 break;
105 }
106 }
107 buffer.append('\'');
108}
109
110}
111
112void SAL_CALL CmdMailSuppl::sendSimpleMailMessage( const Reference< XSimpleMailMessage >& xSimpleMailMessage, sal_Int32 /*aFlag*/ )
113{
114 if ( ! xSimpleMailMessage.is() )
115 {
116 throw css::lang::IllegalArgumentException( "No message specified" ,
117 static_cast < XSimpleMailClient * > (this), 1 );
118 }
119
120 if( ! m_xConfigurationProvider.is() )
121 {
122 throw css::uno::Exception( "Can not access configuration" ,
123 static_cast < XSimpleMailClient * > (this) );
124 }
125
126
127 OUString aProgramURL("$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/senddoc");
128 rtl::Bootstrap::expandMacros(aProgramURL);
129
130 OUString aProgram;
131 if ( FileBase::E_None != FileBase::getSystemPathFromFileURL(aProgramURL, aProgram))
132 {
133 throw css::uno::Exception("Could not convert executable path",
134 static_cast < XSimpleMailClient * > (this));
135 }
136
137 OStringBuffer aBuffer;
138 appendShellWord(aBuffer, aProgram, true);
139
140 try
141 {
142 // Query XNameAccess interface of the org.openoffice.Office.Common/ExternalMailer
143 // configuration node to retrieve the users preferred email application. This may
144 // transparently by redirected to e.g. the corresponding GConf setting in GNOME.
145
146 PropertyValue aProperty;
147 aProperty.Name = "nodepath";
148 aProperty.Value <<= OUString("org.openoffice.Office.Common/ExternalMailer");
149
150 Sequence< Any > aArgumentList{ Any(aProperty) };
151
152 Reference< XNameAccess > xNameAccess(
153 m_xConfigurationProvider->createInstanceWithArguments(
154 "com.sun.star.configuration.ConfigurationAccess",
155 aArgumentList ),
156 UNO_QUERY );
157
158 if( xNameAccess.is() )
159 {
160 OUString aMailer;
161
162 // Retrieve the value for "Program" node and append it feed senddoc with it
163 // using the (undocumented) --mailclient switch
164 xNameAccess->getByName("Program") >>= aMailer;
165
166 if( !aMailer.isEmpty() )
167 {
168 // make sure we have a system path
169 FileBase::getSystemPathFromFileURL( aMailer, aMailer );
170
171 aBuffer.append(" --mailclient ");
172 appendShellWord(aBuffer, aMailer, true);
173 }
174#ifdef MACOSX
175 else
176 aBuffer.append(" --mailclient Mail");
177#endif
178 }
179
180 }
181
182 catch(const RuntimeException & )
183 {
184 TOOLS_WARN_EXCEPTION("shell", "RuntimeException caught accessing configuration provider" );
186 throw;
187 }
188
189 Reference< XSimpleMailMessage2 > xMessage( xSimpleMailMessage, UNO_QUERY );
190 if ( xMessage.is() )
191 {
192 OUString sBody = xMessage->getBody();
193 if ( sBody.getLength() > 0 )
194 {
195 aBuffer.append(" --body ");
196 appendShellWord(aBuffer, sBody, false);
197 }
198 }
199
200 // Convert from, to, etc. in a best-effort rather than a strict way to the
201 // system encoding, based on the assumption that the relevant address parts
202 // of those strings are ASCII anyway and any problematic characters are only
203 // in the human-readable, informational-only parts:
204
205 // Append originator if set in the message
206 if ( !xSimpleMailMessage->getOriginator().isEmpty() )
207 {
208 aBuffer.append(" --from ");
209 appendShellWord(aBuffer, xSimpleMailMessage->getOriginator(), false);
210 }
211
212 // Append recipient if set in the message
213 if ( !xSimpleMailMessage->getRecipient().isEmpty() )
214 {
215 aBuffer.append(" --to ");
216 appendShellWord(aBuffer, xSimpleMailMessage->getRecipient(), false);
217 }
218
219 // Append carbon copy recipients set in the message
220 Sequence< OUString > aStringList = xSimpleMailMessage->getCcRecipient();
221 for ( const auto& rString : std::as_const(aStringList) )
222 {
223 aBuffer.append(" --cc ");
224 appendShellWord(aBuffer, rString, false);
225 }
226
227 // Append blind carbon copy recipients set in the message
228 aStringList = xSimpleMailMessage->getBccRecipient();
229 for ( const auto& rString : std::as_const(aStringList) )
230 {
231 aBuffer.append(" --bcc ");
232 appendShellWord(aBuffer, rString, false);
233 }
234
235 // Append subject if set in the message
236 if ( !xSimpleMailMessage->getSubject().isEmpty() )
237 {
238 aBuffer.append(" --subject ");
239 appendShellWord(aBuffer, xSimpleMailMessage->getSubject(), false);
240 }
241
242 // Append attachments set in the message
243 aStringList = xSimpleMailMessage->getAttachement();
244 for ( const auto& rString : std::as_const(aStringList) )
245 {
246 OUString aSystemPath;
247 if ( FileBase::E_None == FileBase::getSystemPathFromFileURL(rString, aSystemPath) )
248 {
249 aBuffer.append(" --attach ");
250 appendShellWord(aBuffer, aSystemPath, true);
251 }
252 }
253
254 OString cmd = aBuffer.makeStringAndClear();
255 FILE * f = popen(cmd.getStr(), "w");
256 if (f == nullptr || pclose(f) != 0)
257 {
258 throw css::uno::Exception("No mail client configured",
259 static_cast < XSimpleMailClient * > (this) );
260 }
261}
262
263// XServiceInfo
264
266{
267 return "com.sun.star.comp.system.SimpleCommandMail";
268}
269
270sal_Bool SAL_CALL CmdMailSuppl::supportsService( const OUString& ServiceName )
271{
273}
274
276{
277 return { "com.sun.star.system.SimpleCommandMail" };
278}
279
280extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
282 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
283{
284 return cppu::acquire(new CmdMailSuppl(context));
285}
286
287/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::lang::XMultiServiceFactory > m_xConfigurationProvider
CmdMailSuppl(const css::uno::Reference< css::uno::XComponentContext > &xContext)
virtual css::uno::Reference< css::system::XSimpleMailMessage > SAL_CALL createSimpleMailMessage() override
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL sendSimpleMailMessage(const css::uno::Reference< css::system::XSimpleMailMessage > &xSimpleMailMessage, sal_Int32 aFlag) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::uno::Reference< css::system::XSimpleMailClient > SAL_CALL querySimpleMailClient() override
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * shell_CmdMailSuppl_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
#define TOOLS_WARN_EXCEPTION(area, stream)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
unsigned char sal_Bool
const std::u16string_view aStringList[]
std::unique_ptr< char[]> aBuffer