From 793fb097fdb9d4150ac282a7ea9a839d895325f5 Mon Sep 17 00:00:00 2001 From: Shawn Jackson Date: Wed, 2 Sep 2026 14:38:59 -0700 Subject: [PATCH 1/2] RG-T134 Fixing email issues, adding fallback copy/paste urls in email. --- Core/Resgrid.Services/EmailService.cs | 4 +- .../PostmarkTemplateProvider.cs | 180 ++++++++--- .../Template/Call.html | 20 +- .../Template/Cancelled.html | 17 +- .../Template/ChargeFailed.html | 21 +- .../Template/CommunicationTest.html | 2 +- .../Template/DeleteDepartment.html | 4 +- .../Template/DepartmentLinkCreated.html | 2 +- .../Template/Invitation.html | 8 +- .../Template/Message.html | 39 +-- .../PasswordChangedByAdministrator.html | 30 +- .../Template/PasswordRecovery.html | 36 ++- .../Template/Receipt.html | 18 +- .../Template/ReportDelivery.html | 34 +- .../Template/TroubleAlert.html | 4 +- .../Template/Welcome.html | 8 +- .../PasswordRecoveryEmailTemplateTests.cs | 94 ++++++ .../TransactionalEmailTemplateTests.cs | 297 ++++++++++++++++++ .../Services/EmailServiceUsabilityTests.cs | 88 ++++++ 19 files changed, 765 insertions(+), 141 deletions(-) create mode 100644 Tests/Resgrid.Tests/Providers/PasswordRecoveryEmailTemplateTests.cs create mode 100644 Tests/Resgrid.Tests/Providers/TransactionalEmailTemplateTests.cs create mode 100644 Tests/Resgrid.Tests/Services/EmailServiceUsabilityTests.cs diff --git a/Core/Resgrid.Services/EmailService.cs b/Core/Resgrid.Services/EmailService.cs index 2c4736a0..d1659c61 100644 --- a/Core/Resgrid.Services/EmailService.cs +++ b/Core/Resgrid.Services/EmailService.cs @@ -382,8 +382,8 @@ public async Task SendTroubleAlert(TroubleAlertEvent troubleAlertEvent, Un if (profile != null && profile.SendEmail && !String.IsNullOrWhiteSpace(emailAddress)) { - await _emailProvider.SendTroubleAlertMail(emailAddress, unit.Name, gpsLocation, "", callAddress, - unitAddress, "", callName); + await _emailProvider.SendTroubleAlertMail(emailAddress, unit.Name, gpsLocation, personnelNames, callAddress, + unitAddress, dispatchedOn, callName); return true; } diff --git a/Providers/Resgrid.Providers.Email/PostmarkTemplateProvider.cs b/Providers/Resgrid.Providers.Email/PostmarkTemplateProvider.cs index 4c03e3f0..6c9fc700 100644 --- a/Providers/Resgrid.Providers.Email/PostmarkTemplateProvider.cs +++ b/Providers/Resgrid.Providers.Email/PostmarkTemplateProvider.cs @@ -16,10 +16,10 @@ public class PostmarkTemplateProvider : IEmailProvider private static string FROM_EMAIL = OutboundEmailServerConfig.FromMail; private static string DONOTREPLY_EMAIL = OutboundEmailServerConfig.FromMail; - private static string LOGIN_URL = $"{SystemBehaviorConfig.ResgridBaseUrl}/Account/LogOn"; + private static string LOGIN_URL => GetAppUrl("Account/LogOn"); private static string LIVECHAT_URL = $"https://resgrid.com/contact"; - private static string HELP_URL = "https://resgrid.zohodesk.com/portal/en/homem"; - private static string UPDATEBILLINGINFO_URL = $"{SystemBehaviorConfig.ResgridBaseUrl}/User/Subscription/UpdateBillingInfo"; + private static string HELP_URL = "https://resgrid.zohodesk.com/portal/en/home"; + private static string UPDATEBILLINGINFO_URL => GetAppUrl("User/Subscription/UpdateBillingInfo"); public PostmarkTemplateProvider(IEmailSender emailSender) { @@ -54,8 +54,8 @@ public async Task SendDeleteDepartmentEmail(string requesterName, string d { "department_name", departmentName }, { "local_deletion_date", localCompletedOn.ToString("F") }, { "name", sendingToPersonName }, - { "login_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/Account/LogOn" }, - { "support_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/Home/Contact" }, + { "login_url", GetAppUrl("Account/LogOn") }, + { "support_url", GetAppUrl("Home/Contact") }, }; try @@ -102,17 +102,21 @@ public async Task SendCallMail(string email, string subject, string title, { "priority", priority }, { "address", address }, { "map_page", mapPage }, - { "action_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/User/Dispatch/CallExportEx?query={callQuery}" }, - { "userId", userId }, - { "coordinates", coordinates } + { "action_url", GetAppUrl($"User/Dispatch/CallExportEx?query={Uri.EscapeDataString(callQuery)}") }, + { "coordinates", coordinates }, + { + "call_audio", String.IsNullOrWhiteSpace(shortenedAudioUrl) + ? Array.Empty>() + : new[] + { + new Dictionary + { + { "url", System.Net.WebUtility.HtmlEncode(shortenedAudioUrl) } + } + } + } }; - if (!String.IsNullOrWhiteSpace(shortenedAudioUrl)) - { - templateModel.Add("hasCallAudio", "true"); - templateModel.Add("callAudio_url", shortenedAudioUrl); - } - try { @@ -174,13 +178,13 @@ public async Task SendCancellationReciept(string name, string email, strin { var templateModel = new Dictionary { - { "action_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/User/Subscription" }, - { "subscriptions_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/User/Subscription" }, + { "greeting", String.IsNullOrWhiteSpace(name) ? "Hello," : $"Hi {System.Net.WebUtility.HtmlEncode(name)}," }, + { "department_name", System.Net.WebUtility.HtmlEncode(departmentName) }, + { "end_date", System.Net.WebUtility.HtmlEncode(endDate) }, + { "action_url", GetAppUrl("User/Subscription") }, + { "subscriptions_url", GetAppUrl("User/Subscription") }, { "help_url", HELP_URL }, - { "trial_extension_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/User/Subscription" }, - { "export_url", "" }, { "plans_url", $"https://resgrid.com/pricing" }, - { "close_account_url", HELP_URL }, }; try @@ -208,13 +212,13 @@ public async Task SendChargeFailed(string name, string email, string endDa { var templateModel = new Dictionary { - { "plan_name", planName }, + { "greeting", String.IsNullOrWhiteSpace(name) ? "Hello," : $"Hi {System.Net.WebUtility.HtmlEncode(name)}," }, + { "department_name", System.Net.WebUtility.HtmlEncode(departmentName) }, + { "end_date", System.Net.WebUtility.HtmlEncode(endDate) }, + { "plan_name", System.Net.WebUtility.HtmlEncode(planName) }, { "action_url", UPDATEBILLINGINFO_URL }, - { "subscriptions_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/User/Subscription" }, + { "subscriptions_url", GetAppUrl("User/Subscription") }, { "help_url", HELP_URL }, - { "trial_extension_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/User/Subscription" }, - { "export_url", "" }, - { "close_account_url", HELP_URL }, }; try @@ -240,11 +244,14 @@ public async Task SendChargeFailed(string name, string email, string endDa public async Task SendInviteMail(string code, string departmentName, string email, string senderName, string senderEmail) { + if (String.IsNullOrWhiteSpace(code)) + return false; + var templateModel = new Dictionary { { "invite_sender_name", senderName }, { "department_name", departmentName }, - { "action_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/Account/CompleteInvite?inviteCode={code}" }, + { "action_url", GetAppUrl($"Account/CompleteInvite?inviteCode={Uri.EscapeDataString(code)}") }, { "support_email", FROM_EMAIL }, { "live_chat_url", LIVECHAT_URL }, { "help_url", HELP_URL }, @@ -279,11 +286,10 @@ public async Task SendMessageMail(string email, string subject, string mes var templateModel = new Dictionary { { "sender_name", senderName }, - { "title", subject }, + { "title", messageSubject }, { "body", HtmlToTextHelper.ConvertHtml(messageBody) }, - { "action_url", $"https://app.resgrid.com/User/Messages/ViewMessage?messageId={messageId}" }, + { "action_url", GetAppUrl($"User/Messages/ViewMessage?messageId={messageId}") }, { "timestamp", sentOn }, - { "commenter_name", senderName } }; try @@ -295,8 +301,10 @@ public async Task SendMessageMail(string email, string subject, string mes newEmail.HtmlBody = content; newEmail.Sender = FROM_EMAIL; newEmail.From = FROM_EMAIL; - newEmail.Subject = $"Resgrid New Message: {subject}"; + newEmail.Subject = subject; newEmail.To.Add(email); + if (!String.IsNullOrWhiteSpace(senderEmail)) + newEmail.ReplyTo.Add(senderEmail); return await _emailSender.Send(newEmail); } @@ -311,16 +319,30 @@ public async Task SendPasswordRecoveryMail(string name, string email, string departmentName, string resetUrl, string ipAddress, string userAgent, string requestedOn, bool isSsoManaged) { + if (!isSsoManaged && String.IsNullOrWhiteSpace(resetUrl)) + return false; + var templateModel = new Dictionary { { "name", System.Net.WebUtility.HtmlEncode(name) }, { "department_name", System.Net.WebUtility.HtmlEncode(departmentName) }, { "support_url", LIVECHAT_URL }, - { "reset_url", System.Net.WebUtility.HtmlEncode(resetUrl) }, { "ip_address", System.Net.WebUtility.HtmlEncode(ipAddress) }, { "user_agent", System.Net.WebUtility.HtmlEncode(userAgent) }, { "requested_on", System.Net.WebUtility.HtmlEncode(requestedOn) }, - { "has_reset_link", !isSsoManaged }, + // Mustachio resolves fields in an each block against the current item, so the + // URL must live in that item instead of beside a boolean section flag. + { + "reset_link", isSsoManaged + ? Array.Empty>() + : new[] + { + new Dictionary + { + { "url", System.Net.WebUtility.HtmlEncode(resetUrl) } + } + } + }, { "is_sso_managed", isSsoManaged }, }; @@ -328,9 +350,41 @@ public async Task SendPasswordRecoveryMail(string name, string email, { var template = Mustachio.Parser.Parse(GetTempate("PasswordRecovery.html")); var content = template(templateModel); + var textContent = new StringBuilder(); + textContent.AppendLine("Password reset requested"); + textContent.AppendLine(); + textContent.AppendLine($"Hi {name},"); + textContent.AppendLine(); + textContent.AppendLine( + $"You or an administrator requested a password reset for your Resgrid account in {departmentName}."); + textContent.AppendLine(); + + if (isSsoManaged) + { + textContent.AppendLine( + "This account is linked via SSO and cannot change its password via the Resgrid system. Contact your administrator."); + } + else + { + textContent.AppendLine("Choose a new password using this short-lived, single-use link:"); + textContent.AppendLine(resetUrl); + textContent.AppendLine(); + textContent.AppendLine( + "Changing your password will immediately sign you out of every Resgrid web, mobile, dispatch, and big-board session and revoke all existing access and refresh tokens."); + } + + textContent.AppendLine(); + textContent.AppendLine("Request details"); + textContent.AppendLine($"Time (UTC): {requestedOn}"); + textContent.AppendLine($"IP address: {ipAddress}"); + textContent.AppendLine($"Browser/device: {userAgent}"); + textContent.AppendLine(); + textContent.AppendLine( + $"If you did not expect this request, no password has been changed. Contact your administrator or Resgrid support at {LIVECHAT_URL} if you are concerned."); Email newEmail = new Email(); newEmail.HtmlBody = content; + newEmail.TextBody = textContent.ToString(); newEmail.Sender = FROM_EMAIL; newEmail.From = FROM_EMAIL; newEmail.Subject = "Resgrid password reset request"; @@ -361,9 +415,24 @@ public async Task SendPasswordChangedByAdministratorMail(string name, stri { var template = Mustachio.Parser.Parse(GetTempate("PasswordChangedByAdministrator.html")); var content = template(templateModel); + var textContent = new StringBuilder(); + textContent.AppendLine("Your Resgrid password was changed"); + textContent.AppendLine(); + textContent.AppendLine($"Hi {name},"); + textContent.AppendLine(); + textContent.AppendLine( + $"An administrator in {departmentName} changed the password for your Resgrid account {userName}."); + textContent.AppendLine( + "All existing Resgrid sessions were signed out. Use the new password supplied by your administrator."); + textContent.AppendLine(); + textContent.AppendLine($"Log in: {LOGIN_URL}"); + textContent.AppendLine(); + textContent.AppendLine( + $"If you did not expect this change, contact your department administrator or Resgrid support at {LIVECHAT_URL}."); var newEmail = new Email { HtmlBody = content, + TextBody = textContent.ToString(), Sender = FROM_EMAIL, From = FROM_EMAIL, Subject = "Your Resgrid password was changed" @@ -385,6 +454,9 @@ public async Task SendPaymentReciept(string departmentName, string name, s { { "purchase_date", processDate }, { "name", name }, + { "department_name", departmentName }, + { "next_billing_date", nextBillingDate }, + { "processor", processor }, { "billing_url", UPDATEBILLINGINFO_URL }, { "uservoice_url", LIVECHAT_URL }, { "receipt_id", transactionId }, @@ -401,10 +473,7 @@ public async Task SendPaymentReciept(string departmentName, string name, s }, { "total", amount }, { "support_url", HELP_URL }, - { "action_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}User/Subscription/ViewInvoice?paymentId={paymentId}" }, - { "credit_card_brand", "" }, - { "credit_card_last_four", "" }, - { "expiration_date", "" }, + { "action_url", GetAppUrl($"User/Subscription/ViewInvoice?paymentId={paymentId}") }, }; try @@ -450,8 +519,7 @@ public async Task SendWelcomeMail(string name, string departmentName, stri var templateModel = new Dictionary { { "name", name }, - { "action_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}" }, - { "login_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/Account/LogOn" }, + { "login_url", GetAppUrl("Account/LogOn") }, { "department_id", departmentId }, { "department_name", departmentName }, { "username", userName }, @@ -498,8 +566,7 @@ public async Task SendNewDepartmentLinkMail(string name, string department var templateModel = new Dictionary { { "name", name }, - { "action_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}" }, - { "login_url", $"{Config.SystemBehaviorConfig.ResgridBaseUrl}/Account/LogOn" }, + { "login_url", GetAppUrl("Account/LogOn") }, { "department_name", departmentName }, { "data", data }, { "support_email", FROM_EMAIL }, @@ -531,22 +598,30 @@ public async Task SendNewDepartmentLinkMail(string name, string department public async Task SendReportDeliveryMail(string email, string subject, string messageBody, string sentOn, string reportName, string attachmentFilename, byte[] attachmentData, string reportUrl) { + if (attachmentData == null) + return false; + var templateModel = new Dictionary { { "title", subject }, + { "report_name", reportName }, { "body", HtmlToTextHelper.ConvertHtml(messageBody) }, - { "attachment_details", new []{ - new Dictionary { - { "attachmnet_url", reportUrl}, - { "url_name", "View Live Report" }, - { "attachment_name", attachmentFilename }, - { "attachment_size", StringHelpers.GetSizeInMemory(attachmentData.LongLength) }, - { "attachment_type", "PDF" }, - } - } + { "attachment_name", attachmentFilename }, + { "attachment_size", StringHelpers.GetSizeInMemory(attachmentData.LongLength) }, + { "attachment_type", "PDF" }, + { + "report_links", String.IsNullOrWhiteSpace(reportUrl) + ? Array.Empty>() + : new[] + { + new Dictionary + { + { "url", reportUrl } + } + } }, - { "action_url", $"{SystemBehaviorConfig.ResgridBaseUrl}/User/Profile/Reporting" }, + { "action_url", GetAppUrl("User/Profile/Reporting") }, { "timestamp", sentOn } }; @@ -579,7 +654,7 @@ public async Task SendCommunicationTestMail(string email, CommunicationTes // The model is built before the try below, so without this a null content would throw past // the catch that turns every other failure here into a recorded false. A send that cannot be // composed is a failed send, same as one the provider rejects. - if (content == null) + if (content == null || String.IsNullOrWhiteSpace(content.ConfirmUrl)) return false; // Every string arrives already rendered in the recipient's language -- the template only @@ -639,5 +714,10 @@ private string GetTempate(string templateName) } } } + + private static string GetAppUrl(string relativePath) + { + return $"{SystemBehaviorConfig.ResgridBaseUrl?.TrimEnd('/')}/{relativePath.TrimStart('/')}"; + } } } diff --git a/Providers/Resgrid.Providers.Email/Template/Call.html b/Providers/Resgrid.Providers.Email/Template/Call.html index fd37cbec..df290405 100644 --- a/Providers/Resgrid.Providers.Email/Template/Call.html +++ b/Providers/Resgrid.Providers.Email/Template/Call.html @@ -1,5 +1,5 @@  - + @@ -451,7 +451,7 @@

{{subject}}

- {{#hasCallAudio}} + {{#each call_audio}} @@ -464,7 +464,7 @@

{{subject}}

- Listen To Dispatch Audio + Listen to dispatch audio
@@ -474,13 +474,21 @@

{{subject}}

- {{/hasCallAudio}} + + + + +
+

If the audio button does not work, copy and paste this URL into your web browser.

+

{{url}}

+
+ {{/each}}
-

If you’re having trouble with the button above, copy and paste the URL below into your web browser.

-

{{action_url}} or audio {{callAudio_url}}

+

If the call button does not work, copy and paste this URL into your web browser.

+

{{action_url}}

diff --git a/Providers/Resgrid.Providers.Email/Template/Cancelled.html b/Providers/Resgrid.Providers.Email/Template/Cancelled.html index 0e5fabaf..d8cc07a7 100644 --- a/Providers/Resgrid.Providers.Email/Template/Cancelled.html +++ b/Providers/Resgrid.Providers.Email/Template/Cancelled.html @@ -1,5 +1,5 @@  - + @@ -404,7 +404,8 @@

Your Resgrid subscription has been canceled

-

Thanks for using Resgrid. Your account will be downgraded automatically to the free plan. You've added a lot of data, so here are several options for you to consider going forward.

+

{{greeting}}

+

Your subscription for {{department_name}} remains active through {{end_date}}. After that date, the account will be downgraded automatically to the free plan. Here are several options for you to consider.

@@ -441,12 +442,12 @@

Your Resgrid subscription has been canceled

- +
- Use the Free Plan - You can just continue to use Resgrid on the free plan. You can always upgrade at any time in the future and you still get all the great Resgrid benifits at no cost.
+ Use the Free Plan - You can continue to use Resgrid on the free plan and upgrade again at any time.

Close your account - You can open a ticket with us to close your account and delete your data. Or, do nothing and we'll automatically delete the data over the free limit for you in 90 days.Close your account - Open a support ticket if you want to close your account and delete its data. Otherwise, data above the free-plan limit will be deleted automatically after 90 days.
@@ -458,6 +459,14 @@

Your Resgrid subscription has been canceled


The Resgrid Team

P.S. If you have any questions or need any help, please don't hesitate to reach out. You can reply to this email or join us on live chat during business hours.

+ + + + +
+

If the upgrade button does not work, copy and paste this URL into your web browser.

+

{{action_url}}

+
diff --git a/Providers/Resgrid.Providers.Email/Template/ChargeFailed.html b/Providers/Resgrid.Providers.Email/Template/ChargeFailed.html index e9db5776..502c8ea7 100644 --- a/Providers/Resgrid.Providers.Email/Template/ChargeFailed.html +++ b/Providers/Resgrid.Providers.Email/Template/ChargeFailed.html @@ -1,5 +1,5 @@  - + @@ -391,7 +391,7 @@ @@ -403,9 +403,10 @@ @@ -454,6 +455,14 @@

We were unable to charge your card for your {{plan_name}} plan.


The Resgrid Team

P.S. If you have any questions or need any help, please don't hesitate to reach out. You can reply to this email or join us on live chat during business hours.

+ + + + +
+

If the update button does not work, copy and paste this URL into your web browser.

+

{{action_url}}

+
diff --git a/Providers/Resgrid.Providers.Email/Template/CommunicationTest.html b/Providers/Resgrid.Providers.Email/Template/CommunicationTest.html index 93a501cf..4efd31ce 100644 --- a/Providers/Resgrid.Providers.Email/Template/CommunicationTest.html +++ b/Providers/Resgrid.Providers.Email/Template/CommunicationTest.html @@ -1,5 +1,5 @@  - + diff --git a/Providers/Resgrid.Providers.Email/Template/DeleteDepartment.html b/Providers/Resgrid.Providers.Email/Template/DeleteDepartment.html index 0ab99f6a..c75e6bc2 100644 --- a/Providers/Resgrid.Providers.Email/Template/DeleteDepartment.html +++ b/Providers/Resgrid.Providers.Email/Template/DeleteDepartment.html @@ -1,5 +1,5 @@  - + @@ -406,7 +406,7 @@

Hi {{name}},

{{requester_name}} has requested the deletion of your Resgrid department named {{department_name}}. This is scheduled to occur after {{local_deletion_date}}. If this was made in error you can cancel the pending request. Otherwise do nothing to let it proceed normally.

-

Please note, this process is not reversable once complete. We recommend only using Resgrid to download and save any data you wish to keep and not make any changes as that can cause issues with the deletion process.

+

Please note that this process cannot be reversed once complete. We recommend downloading any data you wish to keep and avoiding further changes that could interfere with the deletion process.

You can log in here

diff --git a/Providers/Resgrid.Providers.Email/Template/DepartmentLinkCreated.html b/Providers/Resgrid.Providers.Email/Template/DepartmentLinkCreated.html index 26473532..a034b77d 100644 --- a/Providers/Resgrid.Providers.Email/Template/DepartmentLinkCreated.html +++ b/Providers/Resgrid.Providers.Email/Template/DepartmentLinkCreated.html @@ -1,5 +1,5 @@  - + diff --git a/Providers/Resgrid.Providers.Email/Template/Invitation.html b/Providers/Resgrid.Providers.Email/Template/Invitation.html index 1286750b..98bc45e1 100644 --- a/Providers/Resgrid.Providers.Email/Template/Invitation.html +++ b/Providers/Resgrid.Providers.Email/Template/Invitation.html @@ -1,5 +1,5 @@  - + @@ -392,7 +392,7 @@
@@ -420,7 +420,7 @@

Hello,

- Set up account + Set up account
@@ -430,7 +430,7 @@

Hello,

-

If you have any questions for {{invite_sender_name}}, you can email them at {{sender_email}}. Alternatively, feel free to contact our customer success team anytime. (We're lightning quick at replying.) We also offer live chat during business hours.

+

If you have any questions for {{invite_sender_name}}, you can email them directly. Alternatively, feel free to contact our customer success team anytime. We also offer live chat during business hours.

Welcome aboard,
The Resgrid Team diff --git a/Providers/Resgrid.Providers.Email/Template/Message.html b/Providers/Resgrid.Providers.Email/Template/Message.html index 8767c22f..47fb8434 100644 --- a/Providers/Resgrid.Providers.Email/Template/Message.html +++ b/Providers/Resgrid.Providers.Email/Template/Message.html @@ -1,5 +1,5 @@  - + @@ -385,10 +385,18 @@ + {{sender_name}} sent you a Resgrid message: {{title}} @@ -450,6 +450,7 @@

{{title}}

By {{sender_name}} at {{timestamp}}

View the message

+

© Resgrid, LLC. All rights reserved.

Resgrid, LLC
3079 Harrison Ave diff --git a/Providers/Resgrid.Providers.Email/Template/PasswordChangedByAdministrator.html b/Providers/Resgrid.Providers.Email/Template/PasswordChangedByAdministrator.html index 632e96a8..3b555b48 100644 --- a/Providers/Resgrid.Providers.Email/Template/PasswordChangedByAdministrator.html +++ b/Providers/Resgrid.Providers.Email/Template/PasswordChangedByAdministrator.html @@ -6,30 +6,40 @@ Your Resgrid password was changed -

-
Resgrid
-
-
+ An administrator changed your Resgrid password. + diff --git a/Providers/Resgrid.Providers.Email/Template/PasswordRecovery.html b/Providers/Resgrid.Providers.Email/Template/PasswordRecovery.html index 3e5e965a..275b5d24 100644 --- a/Providers/Resgrid.Providers.Email/Template/PasswordRecovery.html +++ b/Providers/Resgrid.Providers.Email/Template/PasswordRecovery.html @@ -6,30 +6,39 @@ Resgrid password reset request -
-
Resgrid
-
-
+ Use this secure, single-use link to reset your Resgrid password. + - +
diff --git a/Providers/Resgrid.Providers.Email/Template/Receipt.html b/Providers/Resgrid.Providers.Email/Template/Receipt.html index 5163df8b..a3ded5fd 100644 --- a/Providers/Resgrid.Providers.Email/Template/Receipt.html +++ b/Providers/Resgrid.Providers.Email/Template/Receipt.html @@ -1,5 +1,5 @@  - + @@ -391,7 +391,7 @@ @@ -404,14 +404,14 @@