C#
ReminderService.cs
namespace BlazorBirthdayReminders.Data
{
using Dapper;
using Microsoft.Data.SqlClient;
using System.Data;
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Configuration;
using MimeKit;
using MimeKit.Text;
public interface IReminderService
{
public void SendReminders() { }
}
public class ReminderService : IReminderService
{
// Database connection
private readonly IConfiguration _configuration;
public ReminderService(IConfiguration configuration)
{
_configuration = configuration;
}
public string connectionId = "Default";
private List<Person>? birthdaypeople;
public async Task SendReminders()
{
string? SendTo;
string? EmailSubject;
string? EmailBody;
for (int daysNotice = 7; daysNotice < 22; daysNotice = daysNotice + 7)
{
var parameters = new DynamicParameters();
parameters.Add("@DaysToNextBirthday", daysNotice, DbType.Int32);
IEnumerable<Person> people;
using IDbConnection conn = new SqlConnection(_configuration.GetConnectionString(connectionId));
{
people = await conn.QueryAsync<Person>("spPerson_GetByDaysToNextBirthday", parameters, commandType: CommandType.StoredProcedure);
}
birthdaypeople = people.ToList(); //Convert from IEnumerable to List
foreach (var person in birthdaypeople)
{
SendTo = person.PersonSendReminderTo;
EmailSubject = "It's " + person.PersonFullName + "'s Birthday!";
EmailBody = "<p>Hello</p>";
if (daysNotice == 21)
{
EmailBody = EmailBody + "<p>A bit of warning that it's ";
}
else if (daysNotice == 14)
{
EmailBody = EmailBody + "<p>Don't forget, it's ";
}
else
{
EmailBody = EmailBody + "<p>Better get cracking, it's only " + daysNotice + "days until ";
}
EmailBody = EmailBody + person.PersonFirstName + "'s birthday on " + person.NextBirthday.ToString("dd/MM/yyyy") + ".</p>";
if (person.AgeNextBirthday < 21)
{
EmailBody = EmailBody + "<p>" + person.PersonFirstName + " will be " + person.AgeNextBirthday + ".</p>";
}
EmailBody = EmailBody + "<p>Chris <br/>";
EmailBody = EmailBody + "Chris's automated Birthday Reminder Service<p>";
// Get settings from appsettings
var SmtpHost = _configuration["SmtpHost"];
var SmtpPort = _configuration["SmtpPort"];
var SmtpUserFriendlyName = _configuration["SmtpUserFriendlyName"];
var SmtpUserEmailAddress = _configuration["SmtpUserEmailAddress"];
var SmtpPass = _configuration["SmtpPass"];
// create message
var email = new MimeMessage();
email.From.Add(new MailboxAddress(SmtpUserFriendlyName, SmtpUserEmailAddress));
email.To.Add(new MailboxAddress(SendTo, SendTo));
email.Subject = EmailSubject;
email.Body = new TextPart(TextFormat.Html) { Text = EmailBody };
// send email
using var smtp = new SmtpClient();
{
smtp.Connect(SmtpHost, Int32.Parse(SmtpPort), SecureSocketOptions.StartTls);
smtp.Authenticate(SmtpUserEmailAddress, SmtpPass);
smtp.Send(email);
smtp.Disconnect(true);
smtp.Dispose();
}
}
}
}
}
}
Program.cs
using BlazorBirthdayReminders.Data;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
using Syncfusion.Blazor;
using Hangfire;
using Hangfire.SqlServer;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddScoped<IPersonService, PersonService>();
//builder.Services.AddScoped<IEmailService, EmailService>();
builder.Services.AddTransient<IEmailService, EmailService>(); //Scoped didn't seem to work. Singleton did work.
builder.Services.AddSingleton<IReminderService, ReminderService>();
builder.Services.AddSyncfusionBlazor(options => { options.IgnoreScriptIsolation = true; });
builder.Services.AddHangfire(x => x
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(builder.Configuration.GetConnectionString("Default"), new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
}));
builder.Services.AddHangfireServer();
var app = builder.Build();
///Register Syncfusion license
var SyncfusionLicenceKey = builder.Configuration["SyncfusionLicenceKey"];
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(SyncfusionLicenceKey);
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.UseHangfireDashboard("/dashboard");
//IEmailService EmailService = app.Services.GetRequiredService<IEmailService>(); //Needed for items below
//BackgroundJob.Enqueue(() => EmailService.Send("christopherbell@blazorcode.uk",
// "SUBJECT - The program has started",
// "This is the body of the email. This is the email to say the program has started"));
//BackgroundJob.Schedule(() => EmailService.Send("christopherbell@blazorcode.uk",
// "This is sent after a minute"
// , "Welcome - This was sent one minute after starting"),
// TimeSpan.FromMinutes(1));
//RecurringJob.AddOrUpdate(
// "Run every 5 minutes", () => EmailService.Send("christopherbell@blazorcode.uk",
// "Recurring Email every 5 minutes",
// "Another 5 minutes ticks by...."),
// "*/5 * * * *");
//RecurringJob.AddOrUpdate(
// "Run every day at 10:57", () => EmailService.Send("christopherbell@blazorcode.uk",
// "Recurring Email every day at 10:57",
// "This is the body of the email"),
// "57 10 * * *");
IReminderService ReminderService = app.Services.GetRequiredService<IReminderService>(); //Needed for items below
RecurringJob.AddOrUpdate(
"Daily Birthday Reminder", () => ReminderService.SendReminders(),
"35 16 * * *", TimeZoneInfo.Local);
app.Run();