In part 1 of Implementing a Forgot password, we discussed how to create views and controllers for the process.
The following example will show how to create a custom mailsender service used in part 1.
- An
IMemberMailServiceinterface that defines the methods - A
MemberMailServicethat implements theIMemberMailServiceinterface - A composer that adds the service to the runtime.
IMemberMailService
public interface IMemberMailService
{
Task SendResetPassword(string email, string token);
}
MemberMailService
public class MemberMailService : IMemberMailService
{
private readonly string _fromEmail;
private readonly HostingSettings _hostingSettings;
private readonly ILogger _logger;
private readonly IEmailSender _emailSender;
private readonly IHostingEnvrionment _hostingEnvironment;
private readonly ILocalizationService _localisation;
private readonly IMemberService _memberService;
public MemberMailService(IHostingEnvrionment hostingEnvironment, IOptions<GlobalSettings> globalSettings,IEmailSender emailSender,
ILocalizationService localisation,ILogger<MailMessage> logger,IMemberService memberService,IOptions<ContentSettings> contentSettings,
IOptions<HostingSettings> hostingSettings)
{
_logger = logger;
_emailSender = emailSender;
_hostingEnvironment = hostingEnvironment;
_localisation = localisation;
_memberService = memberService;
_hostingSettings = hostingSettings.Value;
_fromEmail = globalSettings.Value.Smtp?.From != null ? globalSettings.Value.Smtp.From : contentSettings.Value.Notifications.Email;
}
public async Task SendResetPassword(string email, string token)
{
try
{
var member = _memberService.GetByEmail(email);
if (member != null)
{
string baseURL = hostingEnvironment.ApplicationMainUrl.AbsoluteUri;
var resetUrl = baseURL + "/forgotpassword/?id=" + member.Id + "&token=" + token;
var messageBody = _localisation.GetOrCreateDictionaryValue("Forums.ResetBody",$@"<p>Hi {member.Name},</p>
<p>Someone requested a password reset for your account on {_hostingSettings.SiteName}.</p>
<p>If this wasn't you then you can ignore this email, otherwise, please click the following password reset link to continue:</p>
<p>Please go to <a href='{resetUrl}'>here</a> to reset your password</p>
<p>&nnbsp;</p>
<p>Kind regards,<br/>The {_hostingSettings.SiteName} Team</p>");
EmailMessage message = new EmailMessage(_fromEmail,email,_localisation.GetOrCreateDictionaryValue("Forums.ResetSubject", $@"Password reset requested for {_hostingSettings.SiteName}"),messageBody,true);
try
{
// smtp (assuming you've set all this up)
await _emailSender.SendAsync(message, emailType: "Contact");
}
catch (Exception ex)
{
_logger.LogInformation("Failed to send the email - probably because email isn't configured for this site\n {0}", ex.ToString());
}
}
}
catch (Exception ex)
{
_logger.LogError(ex,"Error {0}",ex.Message);
}
}
}
MailServiceComposer
public class MailServiceComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.ManifestFilters().Append<EmailValidationManifestFilter>();
builder.Services.AddScoped<IMemberMailService, MemberMailService>();
}
}
This guide walks through building a real Tiptap extension for the Umbraco backoffice — a DateTime inserter that lets editors insert the current date, time, or both into a Rich Text Editor (RTE) field from a toolbar dropdown menu
building a custom collection view for Umbraco 17 that displays documents as beautiful cards with images, using the new extension system and Lit Element web components.
In this post, I'll show you how to build a flexible, on-the-fly watermarking system using SixLabors.ImageSharp.Web that doesn't require modifying your original images.