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 <osl/diagnose.h>
21 #include <sal/macros.h>
22 #include <rtl/string.hxx>
23 #include <rtl/ustring.hxx>
24 #include <rtl/uri.hxx>
25 #include <osl/thread.hxx>
27 #include "simplemapi.hxx"
36 #if OSL_DEBUG_LEVEL > 2
40 typedef std::vector
<std::string
> StringList_t
;
41 typedef StringList_t::const_iterator StringListIterator_t
;
42 typedef std::vector
<MapiRecipDesc
> MapiRecipientList_t
;
43 typedef std::vector
<MapiFileDesc
> MapiAttachmentList_t
;
45 const int LEN_SMTP_PREFIX
= 5; // "SMTP:"
47 namespace /* private */
55 StringList_t gAttachments
;
60 Add a prefix to an email address. MAPI requires that
61 email addresses have an 'SMTP:' prefix.
64 [in] the email address.
67 [in] the prefix to be added to the email address.
70 the email address prefixed with the specified prefix.
72 inline std::string
prefixEmailAddress(
73 const std::string
& aEmailAddress
,
74 const std::string
& aPrefix
= "SMTP:")
76 return (aPrefix
+ aEmailAddress
);
82 const std::string
& recipAddress
,
83 MapiRecipientList_t
* pMapiRecipientList
)
86 ZeroMemory(&mrd
, sizeof(mrd
));
88 mrd
.ulRecipClass
= recipClass
;
89 mrd
.lpszName
= const_cast<char*>(recipAddress
.c_str()) + LEN_SMTP_PREFIX
;
90 mrd
.lpszAddress
= const_cast<char*>(recipAddress
.c_str());
91 pMapiRecipientList
->push_back(mrd
);
95 void initRecipientList(MapiRecipientList_t
* pMapiRecipientList
)
97 OSL_ASSERT(pMapiRecipientList
->empty());
100 StringListIterator_t iter
= gTo
.begin();
101 StringListIterator_t iter_end
= gTo
.end();
102 for (; iter
!= iter_end
; ++iter
)
103 addRecipient(MAPI_TO
, *iter
, pMapiRecipientList
);
107 iter_end
= gCc
.end();
108 for (; iter
!= iter_end
; ++iter
)
109 addRecipient(MAPI_CC
, *iter
, pMapiRecipientList
);
111 // add bcc recipients
113 iter_end
= gBcc
.end();
114 for (; iter
!= iter_end
; ++iter
)
115 addRecipient(MAPI_BCC
, *iter
, pMapiRecipientList
);
119 void initAttachmentList(MapiAttachmentList_t
* pMapiAttachmentList
)
121 OSL_ASSERT(pMapiAttachmentList
->empty());
123 StringListIterator_t iter
= gAttachments
.begin();
124 StringListIterator_t iter_end
= gAttachments
.end();
125 for (/**/; iter
!= iter_end
; ++iter
)
128 ZeroMemory(&mfd
, sizeof(mfd
));
129 mfd
.lpszPathName
= const_cast<char*>(iter
->c_str());
130 mfd
.nPosition
= sal::static_int_cast
<ULONG
>(-1);
131 pMapiAttachmentList
->push_back(mfd
);
136 void initMapiOriginator(MapiRecipDesc
* pMapiOriginator
)
138 ZeroMemory(pMapiOriginator
, sizeof(MapiRecipDesc
));
140 pMapiOriginator
->ulRecipClass
= MAPI_ORIG
;
141 pMapiOriginator
->lpszName
= const_cast<char*>("");
142 pMapiOriginator
->lpszAddress
= const_cast<char*>(gFrom
.c_str());
146 void initMapiMessage(
147 MapiRecipDesc
* aMapiOriginator
,
148 MapiRecipientList_t
& aMapiRecipientList
,
149 MapiAttachmentList_t
& aMapiAttachmentList
,
150 MapiMessage
* pMapiMessage
)
152 ZeroMemory(pMapiMessage
, sizeof(MapiMessage
));
155 rtl_uString
*subject
= NULL
;
156 rtl_uString_newFromAscii(&subject
, const_cast<char*>(gSubject
.c_str()));
157 rtl_uString
*decoded_subject
= NULL
;
158 rtl_uriDecode(subject
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
, &decoded_subject
);
159 OUString
ou_subject(decoded_subject
);
160 pMapiMessage
->lpszSubject
= strdup(OUStringToOString(ou_subject
, osl_getThreadTextEncoding(), RTL_UNICODETOTEXT_FLAGS_UNDEFINED_QUESTIONMARK
).getStr());
163 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
[0];
170 pMapiMessage
->nFileCount
= aMapiAttachmentList
.size();
173 const char* KnownParameter
[] =
186 const size_t nKnownParameter
= (sizeof(KnownParameter
)/sizeof(KnownParameter
[0]));
189 bool isKnownParameter(const char* aParameterName
)
191 for (size_t i
= 0; i
< nKnownParameter
; i
++)
192 if (_tcsicmp(aParameterName
, KnownParameter
[i
]) == 0)
199 void initParameter(int argc
, char* argv
[])
201 for (int i
= 1; i
< argc
; i
++)
203 if (!isKnownParameter(argv
[i
]))
205 OSL_FAIL("Wrong parameter received");
209 if ((_tcsicmp(argv
[i
], TEXT("--mapi-dialog")) == 0))
211 gMapiFlags
|= MAPI_DIALOG
;
213 else if ((_tcsicmp(argv
[i
], TEXT("--mapi-logon-ui")) == 0))
215 gMapiFlags
|= MAPI_LOGON_UI
;
217 else if ((i
+1) < argc
) // is the value of a parameter available too?
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)
231 else if ((_tcsicmp(argv
[i
], TEXT("--attach")) == 0))
232 gAttachments
.push_back(argv
[i
+1]);
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
246 int main(int argc
, char* argv
[])
249 initParameter(argc
, argv
);
251 #if OSL_DEBUG_LEVEL > 2
255 ULONG ulRet
= MAPI_E_FAILURE
;
261 // we have to set the flag MAPI_NEW_SESSION,
262 // because in the case Outlook xxx (not Outlook Express!)
263 // is installed as Exchange and Mail Client a Profile
264 // selection dialog must appear because we specify no
265 // profile name, so the user has to specify a profile
267 LHANDLE hSession
= 0;
269 MapiRecipDesc mapiOriginator
;
270 MapiRecipientList_t mapiRecipientList
;
271 MapiAttachmentList_t mapiAttachmentList
;
274 initMapiOriginator(&mapiOriginator
);
275 initRecipientList(&mapiRecipientList
);
276 initAttachmentList(&mapiAttachmentList
);
277 initMapiMessage((gFrom
.length() ? &mapiOriginator
: NULL
), mapiRecipientList
, mapiAttachmentList
, &mapiMsg
);
279 ulRet
= mapi
.MAPISendMail(hSession
, 0, &mapiMsg
, gMapiFlags
, 0);
281 // There is no point in treating an aborted mail sending
282 // dialog as an error to be returned as our exit
283 // status. If the user decided to abort sending a document
284 // as mail, OK, that is not an error.
286 // Also, it seems that GroupWise makes MAPISendMail()
287 // return MAPI_E_USER_ABORT even if the mail sending
288 // dialog was not aborted by the user, and the mail was
289 // actually sent just fine. See bnc#660241 (visible to
290 // Novell people only, sorry).
292 if (ulRet
== MAPI_E_USER_ABORT
)
293 ulRet
= SUCCESS_SUCCESS
;
296 catch (const std::runtime_error
&
297 #if OSL_DEBUG_LEVEL > 0
307 #if OSL_DEBUG_LEVEL > 2
310 std::ostringstream oss
;
312 if (gFrom
.length() > 0)
313 oss
<< "--from" << " " << gFrom
<< std::endl
;
315 if (gSubject
.length() > 0)
316 oss
<< "--subject" << " " << gSubject
<< std::endl
;
318 if (gBody
.length() > 0)
319 oss
<< "--body" << " " << gBody
<< std::endl
;
321 StringListIterator_t iter
= gTo
.begin();
322 StringListIterator_t iter_end
= gTo
.end();
323 for (/**/;iter
!= iter_end
; ++iter
)
324 oss
<< "--to" << " " << *iter
<< std::endl
;
327 iter_end
= gCc
.end();
328 for (/**/;iter
!= iter_end
; ++iter
)
329 oss
<< "--cc" << " " << *iter
<< std::endl
;
332 iter_end
= gBcc
.end();
333 for (/**/;iter
!= iter_end
; ++iter
)
334 oss
<< "--bcc" << " " << *iter
<< std::endl
;
336 iter
= gAttachments
.begin();
337 iter_end
= gAttachments
.end();
338 for (/**/;iter
!= iter_end
; ++iter
)
339 oss
<< "--attach" << " " << *iter
<< std::endl
;
341 if (gMapiFlags
& MAPI_DIALOG
)
342 oss
<< "--mapi-dialog" << std::endl
;
344 if (gMapiFlags
& MAPI_LOGON_UI
)
345 oss
<< "--mapi-logon-ui" << std::endl
;
347 MessageBox(NULL
, oss
.str().c_str(), "Arguments", MB_OK
| MB_ICONINFORMATION
);
351 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */