Skip to content

Commit de1442a

Browse files
committed
ews: calendar items - process attendees
1 parent 89d99b2 commit de1442a

File tree

3 files changed

+94
-2
lines changed

3 files changed

+94
-2
lines changed

exch/ews/context.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,59 @@ void EWSContext::toContent(const std::string& dir, tCalendarItem& item, sShape&
19971997
shape.write(NtGlobalObjectId, TAGGED_PROPVAL{PT_BINARY, goid});
19981998
shape.write(NtCleanGlobalObjectId, TAGGED_PROPVAL{PT_BINARY, goid});
19991999
}
2000+
2001+
size_t recipients = (item.RequiredAttendees ? item.RequiredAttendees->size() : 0) +
2002+
(item.OptionalAttendees ? item.OptionalAttendees->size() : 0) +
2003+
(item.Resources ? item.Resources->size() : 0);
2004+
if (recipients) {
2005+
if (!content->children.prcpts && !(content->children.prcpts = tarray_set_init()))
2006+
throw EWSError::NotEnoughMemory(E3288);
2007+
TARRAY_SET* rcpts = content->children.prcpts;
2008+
if (item.RequiredAttendees)
2009+
for (const auto &att : *item.RequiredAttendees)
2010+
att.Mailbox.mkRecipient(rcpts->emplace(), MAPI_TO);
2011+
if (item.OptionalAttendees)
2012+
for (const auto &att : *item.OptionalAttendees)
2013+
att.Mailbox.mkRecipient(rcpts->emplace(), MAPI_CC);
2014+
if (item.Resources)
2015+
for (const auto &att : *item.Resources)
2016+
att.Mailbox.mkRecipient(rcpts->emplace(), MAPI_TO);
2017+
std::string dispName;
2018+
if (!mysql_adaptor_get_user_displayname(m_auth_info.username, dispName))
2019+
throw DispatchError(E3302);
2020+
auto displayName = deconst(dispName.c_str());
2021+
shape.write(TAGGED_PROPVAL{PR_SENT_REPRESENTING_NAME, displayName});
2022+
shape.write(TAGGED_PROPVAL{PR_SENDER_NAME, displayName});
2023+
auto username = deconst(m_auth_info.username);
2024+
shape.write(TAGGED_PROPVAL{PR_SENT_REPRESENTING_SMTP_ADDRESS, username});
2025+
shape.write(TAGGED_PROPVAL{PR_SENDER_SMTP_ADDRESS, username});
2026+
auto addrType = deconst("SMTP");
2027+
shape.write(TAGGED_PROPVAL{PR_SENT_REPRESENTING_ADDRTYPE, addrType});
2028+
shape.write(TAGGED_PROPVAL{PR_SENDER_ADDRTYPE, addrType});
2029+
auto uint0 = construct<uint32_t>(0);
2030+
auto uint1 = construct<uint32_t>(1);
2031+
auto uint5 = construct<uint32_t>(5);
2032+
shape.write(NtMeetingType, TAGGED_PROPVAL{PT_LONG, uint1});
2033+
shape.write(NtPrivate, TAGGED_PROPVAL{PT_BOOLEAN, uint0});
2034+
shape.write(NtAppointmentStateFlags, TAGGED_PROPVAL{PT_LONG, uint1});
2035+
shape.write(NtResponseStatus, TAGGED_PROPVAL{PT_LONG, uint5});
2036+
std::string essdn;
2037+
if (cvt_username_to_essdn(m_auth_info.username, m_plugin.x500_org_name.c_str(),
2038+
mysql_adaptor_get_user_ids, mysql_adaptor_get_domain_ids, essdn) != ecSuccess)
2039+
throw DispatchError(E3085);
2040+
shape.write(TAGGED_PROPVAL{PR_SENT_REPRESENTING_EMAIL_ADDRESS, strcpy(alloc<char>(essdn.size() + 1), essdn.c_str())});
2041+
shape.write(TAGGED_PROPVAL{PR_SENDER_EMAIL_ADDRESS, strcpy(alloc<char>(essdn.size() + 1), essdn.c_str())});
2042+
EMSAB_ENTRYID abEid{0, DT_MAILUSER, essdn.data()};
2043+
EXT_PUSH ext_push;
2044+
static constexpr size_t ABEIDBUFFSIZE = 1280;
2045+
uint8_t* abEidBuff = alloc<uint8_t>(ABEIDBUFFSIZE);
2046+
if (!ext_push.init(abEidBuff, ABEIDBUFFSIZE, EXT_FLAG_UTF16) ||
2047+
ext_push.p_abk_eid(abEid) != pack_result::ok)
2048+
throw DispatchError(E3085);
2049+
BINARY* abEidContainer = construct<BINARY>(BINARY{ext_push.m_offset, {abEidBuff}});
2050+
shape.write(TAGGED_PROPVAL{PR_SENT_REPRESENTING_ENTRYID, abEidContainer});
2051+
shape.write(TAGGED_PROPVAL{PR_SENDER_ENTRYID, abEidContainer});
2052+
}
20002053
}
20012054

20022055
/**

exch/ews/exceptions.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,8 @@ inline std::string E3297(const char* uid) {return fmt::format("E-3297: Failed to
429429
E(3298, "Failed to allocate memory for goid data");
430430
E(3299, "Failed to generate goid data");
431431
E(3300, "Failed to get offset from the timezone definition");
432+
E(3301, "Failed to copy message to sent items");
433+
E(3302, "Failed to get the display name");
432434

433435
#undef E
434436
}

exch/ews/requests.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,19 +243,56 @@ void process(mCreateItemRequest&& request, XMLElement* response, const EWSContex
243243
request.MessageDisposition = Enum::SaveOnly;
244244
if (!request.SendMeetingInvitations)
245245
request.SendMeetingInvitations = Enum::SendToNone;
246-
bool sendMessages = request.MessageDisposition == Enum::SendOnly || request.MessageDisposition == Enum::SendAndSaveCopy;
246+
bool sendMessages = request.MessageDisposition == Enum::SendOnly
247+
|| request.MessageDisposition == Enum::SendAndSaveCopy
248+
|| request.SendMeetingInvitations == Enum::SendOnlyToAll
249+
|| request.SendMeetingInvitations == Enum::SendToAllAndSaveCopy;
247250

248251
data.ResponseMessages.reserve(request.Items.size());
252+
auto proptrue = 1;
249253
for (sItem &item : request.Items) try {
250254
if (!hasAccess)
251255
throw EWSError::AccessDenied(E3130);
252256

253257
mCreateItemResponseMessage msg;
254258
bool persist = !(std::holds_alternative<tMessage>(item) && request.MessageDisposition == Enum::SendOnly);
255-
bool send = std::holds_alternative<tMessage>(item) && sendMessages;
259+
bool send = std::holds_alternative<tMessage>(item) && sendMessages;
256260
auto content = ctx.toContent(dir, *targetFolder, item, persist);
257261
if (persist)
258262
msg.Items.emplace_back(ctx.create(dir, *targetFolder, *content));
263+
if (std::holds_alternative<tCalendarItem>(item) && sendMessages &&
264+
request.SendMeetingInvitations == Enum::SendToAllAndSaveCopy) {
265+
sFolderSpec sentitems = ctx.resolveFolder(tDistinguishedFolderId(Enum::sentitems));
266+
uint64_t newMid;
267+
if (!ctx.plugin().exmdb.allocate_message_id(dir.c_str(),
268+
sentitems.folderId, &newMid))
269+
throw EWSError::InternalServerError(E3132);
270+
BOOL result;
271+
uint64_t messageId = *(*content).proplist.get<uint64_t>(PidTagMid);
272+
if (!ctx.plugin().exmdb.movecopy_message(dir.c_str(), CP_ACP,
273+
messageId, sentitems.folderId, newMid, false, &result)
274+
|| !result)
275+
throw EWSError::InternalServerError(E3301);
276+
const char* username = ctx.effectiveUser(sentitems);
277+
auto now = EWSContext::construct<uint64_t>(rop_util_current_nttime());
278+
TAGGED_PROPVAL props[] = {
279+
{PR_MESSAGE_CLASS, deconst("IPM.Schedule.Meeting.Request")},
280+
{PR_RESPONSE_REQUESTED, &proptrue},
281+
{PR_CLIENT_SUBMIT_TIME, now},
282+
{PR_MESSAGE_DELIVERY_TIME, now},
283+
};
284+
TPROPVAL_ARRAY proplist{std::size(props), props};
285+
PROBLEM_ARRAY problems;
286+
if (!ctx.plugin().exmdb.set_message_properties(dir.c_str(),
287+
username, CP_ACP, newMid, &proplist, &problems))
288+
throw EWSError::ItemSave(E3092);
289+
MESSAGE_CONTENT *sendcontent = nullptr;
290+
if (!ctx.plugin().exmdb.read_message(dir.c_str(),
291+
username, CP_ACP, newMid, &sendcontent)
292+
|| sendcontent == nullptr)
293+
throw EWSError::ItemNotFound(E3143);
294+
ctx.send(dir, messageId, *sendcontent);
295+
}
259296
if (send)
260297
ctx.send(dir, 0, *content);
261298
msg.success();

0 commit comments

Comments
 (0)