private static string FormatEmailBody(GraphInvitation data, RedemptionSettings redemption, InviteTemplate content) { var body = content.TemplateContent; body = body.Replace("{{InvitingOrgName}}", Settings.InvitingOrganization); body = body.Replace("{{InvitationLink}}", data.InviteRedeemUrl); body = body.Replace("{{OrgContactEmail}}", redemption.InviterResponseEmailAddr); return(body); }
private async Task <GraphInvitation> SendGraphInvitationAsync(GraphInvitation invitation, List <GroupObject> groups, string inviterResponseEmailAddr = null, InviteTemplate mailTemplate = null, string accessToken = null) { AdalResponse serverResponse = null; GraphInvitation responseData = new GraphInvitation(); try { var inviteEndPoint = string.Format("{0}/{1}/invitations", Settings.GraphResource, Settings.GraphApiVersion); // Invite user. Your app needs to have User.ReadWrite.All or Directory.ReadWrite.All to invite serverResponse = AdalUtil.CallGraph(inviteEndPoint, invitation, false, null, _user, accessToken); responseData = JsonConvert.DeserializeObject <GraphInvitation>(serverResponse.ResponseContent); if (responseData.id == null) { responseData.ErrorInfo = string.Format("Error: Invite not sent - API error: {0}", serverResponse.Message); return(responseData); } if (groups.Count > 0) { var groupsAdded = AddUserToGroup(responseData.InvitedUser.Id, groups); if (!groupsAdded.Success) { var resErrors = string.Join(", ", groupsAdded.Responses.Where(r => !r.Successful).Select(r => r.Message)); responseData.ErrorInfo += string.Format("\n\rOne or more groups failed while assigning to user \"{0}\" ({1})", responseData.InvitedUserEmailAddress, resErrors); } } if (Settings.UseSMTP) { mailTemplate = mailTemplate ?? Settings.CurrSiteConfig.InviteTemplateContent; var emailSubject = mailTemplate.SubjectTemplate.Replace("{{InvitingOrgName}}", Settings.CurrSiteConfig.InvitingOrg); string body = FormatEmailBody(responseData, inviterResponseEmailAddr, mailTemplate); SendViaSMTP(emailSubject, body, invitation.InvitedUserEmailAddress); } var request = await GuestRequestRules.GetUserAsync(invitation.InvitedUserEmailAddress); request.InvitationResult = responseData; await GuestRequestRules.UpdateAsync(request); return(responseData); } catch (Exception ex) { var reason = (serverResponse == null ? "N/A" : serverResponse.ResponseContent); responseData.ErrorInfo = string.Format("Error: {0}<br>Server response: {1}", ex.Message, reason); return(responseData); } }
private static string FormatEmailBody(GraphInvitation invitation, string inviterResponseEmailAddr, InviteTemplate mailTemplate) { var body = mailTemplate.TemplateContent; body = body.Replace("{{InvitingOrgName}}", Settings.CurrSiteConfig.InvitingOrg); body = body.Replace("{{InvitationLink}}", invitation.InviteRedeemUrl); body = body.Replace("{{InvitationStatus}}", invitation.Status); if (invitation.InvitedUserMessageInfo != null) { body = body.Replace("{{CustomMessage}}", invitation.InvitedUserMessageInfo.CustomizedMessageBody); } body = body.Replace("{{OrgContactEmail}}", inviterResponseEmailAddr); return(body); }
public static async Task <HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { log.Info("SendInvite http trigger started."); GraphInvitation result = null; try { // Deserialize request object to model var request = await req.RetrieveRequestObject <GuestRequest>().ConfigureAwait(false); // Check if user exists in Azure AD var user = await UserManager.GetUserByMailAddress(request.EmailAddress).ConfigureAwait(false); if (user != null) { return(req.CreateErrorResponse(HttpStatusCode.BadRequest, "User already exists in directory.")); } // Get group by account id var group = await GroupsManager.GetGroupByAccountIdAsync(request.AccountId).ConfigureAwait(false); // Check if the group is found if (group != null) { // Send invitation to user result = await InvitationManager .SendInvitationAsync(request, $"https://rubichill.sharepoint.com/sites/{request.AccountId}", group.Id) .ConfigureAwait(false); } else { return(req.CreateErrorResponse(HttpStatusCode.BadRequest, "Azure AD group not found.")); } return(req.CreateResponse(HttpStatusCode.Created, result)); } catch (Exception e) { return(req.CreateErrorResponse(HttpStatusCode.BadRequest, e)); } }
public static async Task <GraphInvitation> SendInvitationAsync(GuestRequest request, string groupUrl, string groupId) { var displayName = $"{request.FirstName} {request.LastName}"; var memberType = GraphMemberType.Guest; GraphResponse <GraphInvitation> response = null; // Setup invitation var inviteEndPoint = $"{Constants.ResourceUrl}/{Constants.GraphApiBetaVersion}/invitations"; var invitation = new GraphInvitation() { InvitedUserDisplayName = displayName, InvitedUserEmailAddress = request.EmailAddress, InviteRedirectUrl = groupUrl, SendInvitationMessage = false, InvitedUserType = memberType.ToString() }; // Invite user via Graph API response = await Client.GetData <GraphInvitation>(HttpMethod.Post, inviteEndPoint, invitation) .ConfigureAwait(false); if (!response.IsSuccessfull) { throw new Exception($"Error: invite not sent - API error: {response.Message}"); } // Add user to group var groupAdded = await AddUserToGroupAsync(response.Data.InvitedUser.Id, groupId).ConfigureAwait(false); if (!groupAdded) { throw new Exception($"Error: could not add user {response.Data.InvitedUserEmailAddress} to group {groupId}"); } // Send email to user if (!await Mailer.SendInvitationEmailAsync(request.EmailAddress, response.Data.InviteRedeemUrl)) { throw new Exception($"Error: invite not send to {request.EmailAddress}."); } return(response.Data); }
public static async Task <string> SendInvitation(GuestRequest request, string profileUrl, PreAuthDomain domainSettings = null) { var displayName = string.Format("{0} {1}", request.FirstName, request.LastName); var useCustomEmailTemplate = false; var redemptionSettings = Settings.SiteRedemptionSettings; var memberType = MemberType.Guest; //use domain custom setting if exists, else use global site config setting if (domainSettings != null) { redemptionSettings = domainSettings.DomainRedemptionSettings; //domainSettings.InviteTemplateContent; memberType = domainSettings.MemberType; if (!string.IsNullOrEmpty(domainSettings.InviteTemplateId)) { useCustomEmailTemplate = true; } } AdalResponse serverResponse = null; try { // Setup invitation var inviteEndPoint = string.Format("{0}/{1}/invitations", Settings.GraphResource, Settings.GraphApiVersion); GraphInvitation invitation = new GraphInvitation(); invitation.InvitedUserDisplayName = displayName; invitation.InvitedUserEmailAddress = request.EmailAddress; invitation.InviteRedirectUrl = profileUrl; invitation.SendInvitationMessage = (!Settings.UseSMTP); invitation.InvitedUserType = memberType.ToString(); if (useCustomEmailTemplate && invitation.SendInvitationMessage && domainSettings.InviteTemplateContent.TemplateContent != null) { invitation.InvitedUserMessageInfo = new InvitedUserMessageInfo { CustomizedMessageBody = domainSettings.InviteTemplateContent.TemplateContent }; } // Invite user. Your app needs to have User.ReadWrite.All or Directory.ReadWrite.All to invite serverResponse = CallGraph(inviteEndPoint, invitation); var responseData = JsonConvert.DeserializeObject <GraphInvitation>(serverResponse.ResponseContent); if (responseData.id == null) { return(string.Format("Error: Invite not sent - API error: {0}", serverResponse.Message)); } if (domainSettings != null) { if (domainSettings.Groups != null && domainSettings.Groups.Count > 0) { var groupsAdded = AddUserToGroup(responseData.InvitedUser.Id, domainSettings.Groups); //todo: log or notify re the negative } } if (Settings.UseSMTP) { var emailSubject = Settings.InvitationEmailSubject.Replace("{{orgname}}", Settings.InvitingOrganization); string body = FormatEmailBody(responseData, redemptionSettings, domainSettings.InviteTemplateContent); SendViaSMTP(emailSubject, body, invitation.InvitedUserEmailAddress); } return(responseData.Status); } catch (Exception ex) { var reason = (serverResponse == null ? "N/A" : serverResponse.ResponseContent); return(string.Format("Error: {0}<br>Server response: {1}", ex.Message, reason)); } }
public async Task <BulkInviteResults> ProcessBulkInvitations(BulkInviteSubmission submission) { var res = new BulkInviteResults(submission.Id); try { var batch = new GraphBatch(); int counter = 0; var inviteEndPoint = string.Format("/{0}/invitations", Settings.GraphApiVersion); var headerColl = new Dictionary <string, string> { { "Content-Type", "application/json" } }; var items = await BulkInviteSubmission.GetGuestRequestsPending(submission.Id); foreach (var item in items) { counter++; // Setup invitation GraphInvitation invitation = new GraphInvitation() { InvitedUserDisplayName = item.EmailAddress, InvitedUserEmailAddress = item.EmailAddress, InviteRedirectUrl = _profileUrl, SendInvitationMessage = (!Settings.UseSMTP), InvitedUserType = submission.MemberType.ToString() }; if (submission.InvitationMessage.Length > 0) { invitation.InvitedUserMessageInfo = new InvitedUserMessageInfo { CustomizedMessageBody = submission.InvitationMessage }; } batch.Requests.Add(new BulkInviteRequest { Id = counter.ToString(), GuestRequestId = item.Id, Request = item, Method = "POST", Headers = headerColl, Url = inviteEndPoint, Body = invitation }); } /* NOTE: * This process is designed to leverage the Microsoft Graph batch processor: * https://developer.microsoft.com/en-us/graph/docs/concepts/json_batching * However, the batch processor is currently (2018) in preview and limited to 20 submissions per request * For the time being, we'll loop the collection and make individual synchronous calls */ //res = SubmitToGraphBatch(batch, submission, userId); res = await SubmitLocally(batch, submission); return(res); } catch (Exception ex) { var msg = "Error processing bulk invitation"; res.ErrorMessage = Logging.WriteToAppLog(msg, System.Diagnostics.EventLogEntryType.Error, ex); await BulkInviteResults.AddItem(res); return(res); } }
public async Task <GraphInvitation> ProcessInvitationAsync(GuestRequest request, PreAuthDomain domainSettings = null) { var displayName = string.Format("{0} {1}", request.FirstName, request.LastName); var useCustomEmailTemplate = false; var redemptionSettings = Settings.CurrSiteConfig.SiteRedemptionSettings; var inviteTemplate = Settings.CurrSiteConfig.InviteTemplateContent; var memberType = MemberType.Guest; //use domain custom setting if exists, else use global site config setting if (domainSettings != null) { redemptionSettings = domainSettings.DomainRedemptionSettings; inviteTemplate = domainSettings.InviteTemplateContent; memberType = domainSettings.MemberType; if (!string.IsNullOrEmpty(domainSettings.InviteTemplateId)) { useCustomEmailTemplate = true; } } try { // Setup invitation GraphInvitation invitation = new GraphInvitation() { InvitedUserDisplayName = displayName, InvitedUserEmailAddress = request.EmailAddress, InviteRedirectUrl = _profileUrl, SendInvitationMessage = (!Settings.UseSMTP), InvitedUserType = memberType.ToString() }; if (useCustomEmailTemplate && invitation.SendInvitationMessage && domainSettings.InviteTemplateContent.TemplateContent != null) { invitation.InvitedUserMessageInfo = new InvitedUserMessageInfo { CustomizedMessageBody = domainSettings.InviteTemplateContent.TemplateContent }; } var groups = new List <GroupObject>(); if (domainSettings != null) { if (domainSettings.Groups != null && domainSettings.Groups.Count > 0) { groups = domainSettings.Groups; } } return(await SendGraphInvitationAsync(invitation, groups, redemptionSettings.InviterResponseEmailAddr, inviteTemplate)); } catch (Exception ex) { return(new GraphInvitation { ErrorInfo = string.Format("Error: {0}", ex.Message) }); } }
/// <summary> /// GraphInvitation is a model from https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/invitation /// Do not alter /// </summary> /// <param name="invitation">The GraphInvitation object transmitted to the B2B Guest API</param> /// <param name="groups">Azure AD groups to assign the guest user to</param> /// <param name="inviterResponseEmailAddr"></param> /// <param name="mailTemplate"></param> /// <param name="accessToken"></param> /// <returns></returns> private async Task <GuestRequest> SendGraphInvitationAsync(GraphInvitation invitation, List <GroupObject> groups, GuestRequest request, string inviterResponseEmailAddr = null, InviteTemplate mailTemplate = null, string accessToken = null) { AdalResponse serverResponse = null; GraphInvitation responseData = new GraphInvitation(); try { var inviteEndPoint = string.Format("{0}/{1}/invitations", Settings.GraphResource, Settings.GraphApiVersion); // Invite user. Your app needs to have User.ReadWrite.All or Directory.ReadWrite.All to invite serverResponse = AdalUtil.CallGraph(inviteEndPoint, invitation, false, null, _user, accessToken); responseData = JsonConvert.DeserializeObject <GraphInvitation>(serverResponse.ResponseContent); request.InvitationResult = responseData; request.Status = responseData.Status; if (responseData.id == null) { //API call failed - put the request back in the queue responseData.ErrorInfo = string.Format("Error: Invite not sent - API error: {0}", serverResponse.Message); request.InvitationResult = responseData; request.Disposition = Disposition.Pending; } else { //invitation API call successful if (responseData.Status.Substring(0, 5) == "Error") { //API call was successful but something failed while trying to process the request - put the request back in the queue request.Disposition = Disposition.Pending; } else { //check to see if groups should be assigned if (groups.Count > 0) { try { var groupsAdded = AddUserToGroup(responseData.InvitedUser.Id, groups); if (!groupsAdded.Success) { //group assignment failed var resErrors = string.Join(", ", groupsAdded.Responses.Where(r => !r.Successful).Select(r => r.Message)); var msg = string.Format("\n\rOne or more groups failed while assigning to user \"{0}\" ({1})", responseData.InvitedUserEmailAddress, resErrors); request.PostProcessingStatus += msg; } } catch (Exception groupEx) { //group assignment errored var msg = string.Format("\n\rAn error occured while assigning a group to user \"{0}\" ({1})", responseData.InvitedUserEmailAddress, groupEx.Message); Logging.WriteToAppLog(msg, EventLogEntryType.Warning, groupEx); request.PostProcessingStatus += msg; } } //check to see if custom mail should be sent if (Settings.UseSMTP) { try { mailTemplate = mailTemplate ?? Settings.CurrSiteConfig.InviteTemplateContent; var emailSubject = mailTemplate.SubjectTemplate.Replace("{{InvitingOrgName}}", Settings.CurrSiteConfig.InvitingOrg); string body = FormatEmailBody(responseData, inviterResponseEmailAddr, mailTemplate); SendViaSMTP(emailSubject, body, invitation.InvitedUserEmailAddress); request.MailSent = true; } catch (Exception mailEx) { var msg = string.Format("\n\rSending invitation failed for user \"{0}\" ({1})", responseData.InvitedUserEmailAddress, mailEx.Message); Logging.WriteToAppLog(msg, EventLogEntryType.Warning, mailEx); request.PostProcessingStatus += msg; } } } } //all attempts complete, UPDATE GuestRequest await GuestRequestRules.UpdateAsync(request); return(request); } catch (Exception ex) { var reason = (serverResponse == null ? "N/A" : serverResponse.ResponseContent); responseData.ErrorInfo = string.Format("Error: {0}<br>Server response: {1}", ex.Message, reason); request.InvitationResult = responseData; //UPDATE GuestRequest await GuestRequestRules.UpdateAsync(request); return(request); } }