1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_shell.hxx" 26 #include <osl/diagnose.h> 27 #include <osl/process.h> 28 #include <rtl/bootstrap.hxx> 29 #include "smplmailclient.hxx" 30 #include "smplmailmsg.hxx" 31 #include <com/sun/star/system/SimpleMailClientFlags.hpp> 32 #include <osl/file.hxx> 33 34 #define WIN32_LEAN_AND_MEAN 35 #if defined _MSC_VER 36 #pragma warning(push, 1) 37 #endif 38 #include <windows.h> 39 #include <mapi.h> 40 #if defined _MSC_VER 41 #pragma warning(pop) 42 #endif 43 44 #include <process.h> 45 #include <vector> 46 47 using css::uno::Reference; 48 using css::uno::Exception; 49 using css::uno::RuntimeException; 50 using css::uno::Sequence; 51 using css::lang::IllegalArgumentException; 52 53 using css::system::XSimpleMailClient; 54 using css::system::XSimpleMailMessage; 55 using css::system::SimpleMailClientFlags::NO_USER_INTERFACE; 56 using css::system::SimpleMailClientFlags::NO_LOGON_DIALOG; 57 58 typedef std::vector<rtl::OUString> StringList_t; 59 typedef StringList_t::const_iterator StringListIterator_t; 60 61 const rtl::OUString TO = rtl::OUString::createFromAscii("--to"); 62 const rtl::OUString CC = rtl::OUString::createFromAscii("--cc"); 63 const rtl::OUString BCC = rtl::OUString::createFromAscii("--bcc"); 64 const rtl::OUString FROM = rtl::OUString::createFromAscii("--from"); 65 const rtl::OUString SUBJECT = rtl::OUString::createFromAscii("--subject"); 66 const rtl::OUString BODY = rtl::OUString::createFromAscii("--body"); 67 const rtl::OUString ATTACH = rtl::OUString::createFromAscii("--attach"); 68 const rtl::OUString FLAG_MAPI_DIALOG = rtl::OUString::createFromAscii("--mapi-dialog"); 69 const rtl::OUString FLAG_MAPI_LOGON_UI = rtl::OUString::createFromAscii("--mapi-logon-ui"); 70 71 namespace /* private */ 72 { 73 /** @internal 74 look if an alternative program is configured 75 which should be used as senddoc executable */ 76 rtl::OUString getAlternativeSenddocUrl() 77 { 78 rtl::OUString altSenddocUrl; 79 HKEY hkey; 80 LONG lret = RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\OpenOffice.org\\SendAsEMailClient", &hkey); 81 if (lret == ERROR_SUCCESS) 82 { 83 wchar_t buff[MAX_PATH]; 84 LONG sz = sizeof(buff); 85 lret = RegQueryValueW(hkey, NULL, buff, &sz); 86 if (lret == ERROR_SUCCESS) 87 { 88 osl::FileBase::getFileURLFromSystemPath(reinterpret_cast<const sal_Unicode*>(buff), altSenddocUrl); 89 } 90 RegCloseKey(hkey); 91 } 92 return altSenddocUrl; 93 } 94 95 /** 96 Returns the absolute file Url of the senddoc executable. 97 98 @returns 99 the absolute file Url of the senddoc executable. In case 100 of an error an empty string will be returned. 101 */ 102 rtl::OUString getSenddocUrl() 103 { 104 rtl::OUString senddocUrl = getAlternativeSenddocUrl(); 105 106 if (senddocUrl.getLength() == 0) 107 { 108 senddocUrl = rtl::OUString( 109 RTL_CONSTASCII_USTRINGPARAM( 110 "$OOO_BASE_DIR/program/senddoc.exe")); 111 rtl::Bootstrap::expandMacros(senddocUrl); //TODO: detect failure 112 } 113 return senddocUrl; 114 } 115 116 /** 117 Execute Senddoc.exe which a MAPI wrapper. 118 119 @param rCommandArgs 120 [in] the arguments to be passed to Senddoc.exe 121 122 @returns 123 <TRUE/> on success. 124 */ 125 bool executeSenddoc(const StringList_t& rCommandArgs) 126 { 127 rtl::OUString senddocUrl = getSenddocUrl(); 128 if (senddocUrl.getLength() == 0) 129 return false; 130 131 oslProcess proc; 132 oslProcessError err = osl_Process_E_Unknown; 133 134 /* for efficiency reasons we are using a 'bad' cast here 135 as a vector or rtl::OUStrings is nothing else than 136 an array of pointers to rtl_uString's */ 137 err = osl_executeProcess( 138 senddocUrl.pData, 139 (rtl_uString**)&rCommandArgs[0], 140 rCommandArgs.size(), 141 osl_Process_WAIT | osl_Process_DETACHED, 142 NULL, 143 NULL, 144 NULL, 145 0, 146 &proc); 147 148 if (err != osl_Process_E_None) 149 return false; 150 151 oslProcessInfo procInfo; 152 procInfo.Size = sizeof(oslProcessInfo); 153 osl_getProcessInfo(proc, osl_Process_EXITCODE, &procInfo); 154 osl_freeProcessHandle(proc); 155 return (procInfo.Code == SUCCESS_SUCCESS); 156 } 157 } // namespace private 158 159 Reference<XSimpleMailMessage> SAL_CALL CSmplMailClient::createSimpleMailMessage() 160 throw (RuntimeException) 161 { 162 return Reference<XSimpleMailMessage>(new CSmplMailMsg()); 163 } 164 165 /** 166 Assemble a command line for SendDoc.exe out of the members 167 of the supplied SimpleMailMessage. 168 169 @param xSimpleMailMessage 170 [in] the mail message. 171 172 @param aFlags 173 [in] different flags to be used with the simple mail service. 174 175 @param rCommandArgs 176 [in|out] a buffer for the command line arguments. The buffer 177 is assumed to be empty. 178 179 @throws com::sun::star::lang::IllegalArgumentException 180 if an invalid file URL has been detected in the attachment list. 181 */ 182 void CSmplMailClient::assembleCommandLine( 183 const Reference<XSimpleMailMessage>& xSimpleMailMessage, 184 sal_Int32 aFlag, StringList_t& rCommandArgs) 185 { 186 OSL_ENSURE(rCommandArgs.size() == 0, "Provided command argument buffer not empty"); 187 188 rtl::OUString to = xSimpleMailMessage->getRecipient(); 189 if (to.getLength() > 0) 190 { 191 rCommandArgs.push_back(TO); 192 rCommandArgs.push_back(to); 193 } 194 195 Sequence<rtl::OUString> ccRecipients = xSimpleMailMessage->getCcRecipient(); 196 for (int i = 0; i < ccRecipients.getLength(); i++) 197 { 198 rCommandArgs.push_back(CC); 199 rCommandArgs.push_back(ccRecipients[i]); 200 } 201 202 Sequence<rtl::OUString> bccRecipients = xSimpleMailMessage->getBccRecipient(); 203 for (int i = 0; i < bccRecipients.getLength(); i++) 204 { 205 rCommandArgs.push_back(BCC); 206 rCommandArgs.push_back(bccRecipients[i]); 207 } 208 209 rtl::OUString from = xSimpleMailMessage->getOriginator(); 210 if (from.getLength() > 0) 211 { 212 rCommandArgs.push_back(FROM); 213 rCommandArgs.push_back(from); 214 } 215 216 rtl::OUString subject = xSimpleMailMessage->getSubject(); 217 if (subject.getLength() > 0) 218 { 219 rCommandArgs.push_back(SUBJECT); 220 rCommandArgs.push_back(subject); 221 } 222 223 Sequence<rtl::OUString> attachments = xSimpleMailMessage->getAttachement(); 224 for (int i = 0; i < attachments.getLength(); i++) 225 { 226 rtl::OUString sysPath; 227 osl::FileBase::RC err = osl::FileBase::getSystemPathFromFileURL(attachments[i], sysPath); 228 if (err != osl::FileBase::E_None) 229 throw IllegalArgumentException( 230 rtl::OUString::createFromAscii("Invalid attachment file URL"), 231 static_cast<XSimpleMailClient*>(this), 232 1); 233 234 rCommandArgs.push_back(ATTACH); 235 rCommandArgs.push_back(sysPath); 236 } 237 238 if (!(aFlag & NO_USER_INTERFACE)) 239 rCommandArgs.push_back(FLAG_MAPI_DIALOG); 240 241 if (!(aFlag & NO_LOGON_DIALOG)) 242 rCommandArgs.push_back(FLAG_MAPI_LOGON_UI); 243 } 244 245 void SAL_CALL CSmplMailClient::sendSimpleMailMessage( 246 const Reference<XSimpleMailMessage>& xSimpleMailMessage, sal_Int32 aFlag) 247 throw (IllegalArgumentException, Exception, RuntimeException) 248 { 249 validateParameter(xSimpleMailMessage, aFlag); 250 251 StringList_t senddocParams; 252 assembleCommandLine(xSimpleMailMessage, aFlag, senddocParams); 253 254 if (!executeSenddoc(senddocParams)) 255 throw Exception( 256 rtl::OUString::createFromAscii("Send email failed"), 257 static_cast<XSimpleMailClient*>(this)); 258 } 259 260 void CSmplMailClient::validateParameter( 261 const Reference<XSimpleMailMessage>& xSimpleMailMessage, sal_Int32 aFlag ) 262 { 263 if (!xSimpleMailMessage.is()) 264 throw IllegalArgumentException( 265 rtl::OUString::createFromAscii("Empty mail message reference"), 266 static_cast<XSimpleMailClient*>(this), 267 1); 268 269 // #93077# 270 OSL_ENSURE(!(aFlag & NO_LOGON_DIALOG), "Flag NO_LOGON_DIALOG has currently no effect"); 271 272 // check the flags, the allowed range is 0 - (2^n - 1) 273 if (aFlag < 0 || aFlag > 3) 274 throw IllegalArgumentException( 275 rtl::OUString::createFromAscii("Invalid flag value"), 276 static_cast<XSimpleMailClient*>(this), 277 2); 278 279 // check if a recipient is specified of the flags NO_USER_INTERFACE is specified 280 if ((aFlag & NO_USER_INTERFACE) && !xSimpleMailMessage->getRecipient().getLength()) 281 throw IllegalArgumentException( 282 rtl::OUString::createFromAscii("No recipient specified"), 283 static_cast<XSimpleMailClient*>(this), 284 1); 285 } 286