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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_shell.hxx"
24 #include <osl/diagnose.h>
25
26 #ifndef _RTL_STRING_HXX_
27 //#include <rtl/string.hxx>
28 #endif
29 #include "sysmapi.hxx"
30
31 #define WIN32_LEAN_AND_MEAN
32 #if defined _MSC_VER
33 #pragma warning(push, 1)
34 #endif
35 #include <windows.h>
36 #if defined _MSC_VER
37 #pragma warning(pop)
38 #endif
39 #include <tchar.h>
40
41 #include <iostream>
42 #include <vector>
43 #include <sstream>
44 #include <stdexcept>
45
46 #if OSL_DEBUG_LEVEL > 2
47 void dumpParameter();
48 #endif
49
50 typedef std::vector<std::string> StringList_t;
51 typedef StringList_t::const_iterator StringListIterator_t;
52 typedef std::vector<MapiRecipDesc> MapiRecipientList_t;
53 typedef std::vector<MapiFileDesc> MapiAttachmentList_t;
54
55 const int LEN_SMTP_PREFIX = 5; // "SMTP:"
56
57 namespace /* private */
58 {
59 std::string gFrom;
60 std::string gSubject;
61 std::string gBody;
62 StringList_t gTo;
63 StringList_t gCc;
64 StringList_t gBcc;
65 StringList_t gAttachments;
66 int gMapiFlags = 0;
67 }
68
69 /**
70 Add a prefix to an email address. MAPI requires that that
71 email addresses have an 'SMTP:' prefix.
72
73 @param aEmailAddress
74 [in] the email address.
75
76 @param aPrefix
77 [in] the prefix to be added to the email address.
78
79 @returns
80 the email address prefixed with the specified prefix.
81 */
prefixEmailAddress(const std::string & aEmailAddress,const std::string & aPrefix="SMTP:")82 inline std::string prefixEmailAddress(
83 const std::string& aEmailAddress,
84 const std::string& aPrefix = "SMTP:")
85 {
86 return (aPrefix + aEmailAddress);
87 }
88
89 /** @internal */
addRecipient(ULONG recipClass,const std::string & recipAddress,MapiRecipientList_t * pMapiRecipientList)90 void addRecipient(
91 ULONG recipClass,
92 const std::string& recipAddress,
93 MapiRecipientList_t* pMapiRecipientList)
94 {
95 MapiRecipDesc mrd;
96 ZeroMemory(&mrd, sizeof(mrd));
97
98 mrd.ulRecipClass = recipClass;
99 mrd.lpszName = const_cast<char*>(recipAddress.c_str()) + LEN_SMTP_PREFIX;
100 mrd.lpszAddress = const_cast<char*>(recipAddress.c_str());
101 pMapiRecipientList->push_back(mrd);
102 }
103
104 /** @internal */
initRecipientList(MapiRecipientList_t * pMapiRecipientList)105 void initRecipientList(MapiRecipientList_t* pMapiRecipientList)
106 {
107 OSL_ASSERT(pMapiRecipientList->size() == 0);
108
109 // add to recipients
110 StringListIterator_t iter = gTo.begin();
111 StringListIterator_t iter_end = gTo.end();
112 for (; iter != iter_end; ++iter)
113 addRecipient(MAPI_TO, *iter, pMapiRecipientList);
114
115 // add cc recipients
116 iter = gCc.begin();
117 iter_end = gCc.end();
118 for (; iter != iter_end; ++iter)
119 addRecipient(MAPI_CC, *iter, pMapiRecipientList);
120
121 // add bcc recipients
122 iter = gBcc.begin();
123 iter_end = gBcc.end();
124 for (; iter != iter_end; ++iter)
125 addRecipient(MAPI_BCC, *iter, pMapiRecipientList);
126 }
127
128 /** @internal */
initAttachementList(MapiAttachmentList_t * pMapiAttachmentList)129 void initAttachementList(MapiAttachmentList_t* pMapiAttachmentList)
130 {
131 OSL_ASSERT(pMapiAttachmentList->size() == 0);
132
133 StringListIterator_t iter = gAttachments.begin();
134 StringListIterator_t iter_end = gAttachments.end();
135 for (/**/; iter != iter_end; ++iter)
136 {
137 MapiFileDesc mfd;
138 ZeroMemory(&mfd, sizeof(mfd));
139 mfd.lpszPathName = const_cast<char*>(iter->c_str());
140 mfd.nPosition = sal::static_int_cast<ULONG>(-1);
141 pMapiAttachmentList->push_back(mfd);
142 }
143 }
144
145 /** @internal */
initMapiOriginator(MapiRecipDesc * pMapiOriginator)146 void initMapiOriginator(MapiRecipDesc* pMapiOriginator)
147 {
148 ZeroMemory(pMapiOriginator, sizeof(MapiRecipDesc));
149
150 pMapiOriginator->ulRecipClass = MAPI_ORIG;
151 pMapiOriginator->lpszName = "";
152 pMapiOriginator->lpszAddress = const_cast<char*>(gFrom.c_str());
153 }
154
155 /** @internal */
initMapiMessage(MapiRecipDesc * aMapiOriginator,MapiRecipientList_t & aMapiRecipientList,MapiAttachmentList_t & aMapiAttachmentList,MapiMessage * pMapiMessage)156 void initMapiMessage(
157 MapiRecipDesc* aMapiOriginator,
158 MapiRecipientList_t& aMapiRecipientList,
159 MapiAttachmentList_t& aMapiAttachmentList,
160 MapiMessage* pMapiMessage)
161 {
162 ZeroMemory(pMapiMessage, sizeof(MapiMessage));
163
164 pMapiMessage->lpszSubject = const_cast<char*>(gSubject.c_str());
165 pMapiMessage->lpszNoteText = (gBody.length() ? const_cast<char*>(gBody.c_str()) : NULL);
166 pMapiMessage->lpOriginator = aMapiOriginator;
167 pMapiMessage->lpRecips = aMapiRecipientList.size() ? &aMapiRecipientList[0] : 0;
168 pMapiMessage->nRecipCount = aMapiRecipientList.size();
169 pMapiMessage->lpFiles = aMapiAttachmentList.size() ? &aMapiAttachmentList[0] : 0;
170 pMapiMessage->nFileCount = aMapiAttachmentList.size();
171 }
172
173 char* KnownParameter[] =
174 {
175 "--to",
176 "--cc",
177 "--bcc",
178 "--from",
179 "--subject",
180 "--body",
181 "--attach",
182 "--mapi-dialog",
183 "--mapi-logon-ui"
184 };
185
186 const size_t nKnownParameter = (sizeof(KnownParameter)/sizeof(KnownParameter[0]));
187
188 /** @internal */
isKnownParameter(const char * aParameterName)189 bool isKnownParameter(const char* aParameterName)
190 {
191 for (size_t i = 0; i < nKnownParameter; i++)
192 if (_tcsicmp(aParameterName, KnownParameter[i]) == 0)
193 return true;
194
195 return false;
196 }
197
198 /** @internal */
initParameter(int argc,char * argv[])199 void initParameter(int argc, char* argv[])
200 {
201 for (int i = 1; i < argc; i++)
202 {
203 if (!isKnownParameter(argv[i]))
204 {
205 OSL_ENSURE(false, "Wrong parameter received");
206 continue;
207 }
208
209 if ((_tcsicmp(argv[i], TEXT("--mapi-dialog")) == 0))
210 {
211 gMapiFlags |= MAPI_DIALOG;
212 }
213 else if ((_tcsicmp(argv[i], TEXT("--mapi-logon-ui")) == 0))
214 {
215 gMapiFlags |= MAPI_LOGON_UI;
216 }
217 else if ((i+1) < argc) // is the value of a parameter available too?
218 {
219 if (_tcsicmp(argv[i], TEXT("--to")) == 0)
220 gTo.push_back(prefixEmailAddress(argv[i+1]));
221 else if (_tcsicmp(argv[i], TEXT("--cc")) == 0)
222 gCc.push_back(prefixEmailAddress(argv[i+1]));
223 else if (_tcsicmp(argv[i], TEXT("--bcc")) == 0)
224 gBcc.push_back(prefixEmailAddress(argv[i+1]));
225 else if (_tcsicmp(argv[i], TEXT("--from")) == 0)
226 gFrom = prefixEmailAddress(argv[i+1]);
227 else if (_tcsicmp(argv[i], TEXT("--subject")) == 0)
228 gSubject = argv[i+1];
229 else if (_tcsicmp(argv[i], TEXT("--body")) == 0)
230 gBody = argv[i+1];
231 else if ((_tcsicmp(argv[i], TEXT("--attach")) == 0))
232 gAttachments.push_back(argv[i+1]);
233
234 i++;
235 }
236 }
237 }
238
239 /**
240 Main.
241 NOTE: Because this is program only serves implementation
242 purposes and should not be used by any end user the
243 parameter checking is very limited. Every unknown parameter
244 will be ignored.
245 */
main(int argc,char * argv[])246 int main(int argc, char* argv[])
247 {
248 //MessageBox(NULL, "Debug", "Debug", MB_OK);
249
250 initParameter(argc, argv);
251
252 #if OSL_DEBUG_LEVEL > 2
253 dumpParameter();
254 #endif
255
256 ULONG ulRet = MAPI_E_FAILURE;
257
258 try
259 {
260 shell::WinSysMapi mapi;
261
262 // #93007# we have to set the flag MAPI_NEW_SESSION,
263 // because in the case Outlook xxx (not Outlook Express!)
264 // is installed as Exchange and Mail Client a Profile
265 // selection dialog must appear because we specify no
266 // profile name, so the user has to specify a profile
267 FLAGS flFlag = MAPI_NEW_SESSION | MAPI_LOGON_UI;
268 LHANDLE hSession;
269 ulRet = mapi.MAPILogon(0, NULL, NULL, flFlag, 0L, &hSession);
270
271 if (ulRet == SUCCESS_SUCCESS)
272 {
273 MapiRecipDesc mapiOriginator;
274 MapiRecipientList_t mapiRecipientList;
275 MapiAttachmentList_t mapiAttachmentList;
276 MapiMessage mapiMsg;
277
278 initMapiOriginator(&mapiOriginator);
279 initRecipientList(&mapiRecipientList);
280 initAttachementList(&mapiAttachmentList);
281 initMapiMessage((gFrom.length() ? &mapiOriginator : NULL), mapiRecipientList, mapiAttachmentList, &mapiMsg);
282
283 ulRet = mapi.MAPISendMail(hSession, 0, &mapiMsg, gMapiFlags, 0);
284
285 mapi.MAPILogoff(hSession, 0, 0, 0);
286 }
287 }
288 catch (const std::runtime_error&
289 #if OSL_DEBUG_LEVEL > 0
290 ex
291 #endif
292 )
293 {
294 OSL_ENSURE(false, ex.what());
295 }
296 return ulRet;
297 }
298
299 #if OSL_DEBUG_LEVEL > 2
dumpParameter()300 void dumpParameter()
301 {
302 std::ostringstream oss;
303
304 if (gFrom.length() > 0)
305 oss << "--from" << " " << gFrom << std::endl;
306
307 if (gSubject.length() > 0)
308 oss << "--subject" << " " << gSubject << std::endl;
309
310 if (gBody.length() > 0)
311 oss << "--body" << " " << gBody << std::endl;
312
313 StringListIterator_t iter = gTo.begin();
314 StringListIterator_t iter_end = gTo.end();
315 for (/**/; iter != iter_end; ++iter)
316 oss << "--to" << " " << *iter << std::endl;
317
318 iter = gCc.begin();
319 iter_end = gCc.end();
320 for (/**/; iter != iter_end; ++iter)
321 oss << "--cc" << " " << *iter << std::endl;
322
323 iter = gBcc.begin();
324 iter_end = gBcc.end();
325 for (/**/; iter != iter_end; ++iter)
326 oss << "--bcc" << " " << *iter << std::endl;
327
328 iter = gAttachments.begin();
329 iter_end = gAttachments.end();
330 for (/**/; iter != iter_end; ++iter)
331 oss << "--attach" << " " << *iter << std::endl;
332
333 if (gMapiFlags & MAPI_DIALOG)
334 oss << "--mapi-dialog" << std::endl;
335
336 if (gMapiFlags & MAPI_LOGON_UI)
337 oss << "--mapi-logon-ui" << std::endl;
338
339 MessageBox(NULL, oss.str().c_str(), "Arguments", MB_OK | MB_ICONINFORMATION);
340 }
341 #endif
342