diff --git a/src/.dockerignore b/src/.dockerignore
index a267a97..7364d76 100644
--- a/src/.dockerignore
+++ b/src/.dockerignore
@@ -1,2 +1,3 @@
**/bin/*
-**/obj/*
\ No newline at end of file
+**/obj/*
+**/appsettings.*
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index d0aaa2c..72b2f28 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -1,11 +1,11 @@
net7.0
- 8.1.0.0
- 8.1.0.0
+ 8.2.0.0
+ 8.2.0.0
danieljsummers
Bit Badger Solutions
- 8.1.0
+ 8.2.0
Embedded
diff --git a/src/PrayerTracker/App.fs b/src/PrayerTracker/App.fs
index 485fd1b..2b9178a 100644
--- a/src/PrayerTracker/App.fs
+++ b/src/PrayerTracker/App.fs
@@ -70,6 +70,9 @@ module Configure =
let _ = dsb.UseNodaTime()
Configuration.useDataSource (dsb.Build ())
+ let emailCfg = cfg.GetSection "Email"
+ if (emailCfg.GetChildren >> Seq.isEmpty >> not) () then ConfigurationBinder.Bind(emailCfg, Email.smtpOptions)
+
let _ = svc.AddSingleton ()
let _ = svc.AddSession ()
let _ = svc.AddAntiforgery ()
@@ -182,19 +185,21 @@ module Configure =
|> function l -> l.AddConsole().AddDebug()
|> ignore
+ open BitBadger.AspNetCore.CanonicalDomains
open Microsoft.Extensions.Localization
open Microsoft.Extensions.Options
/// Configure the application
let app (app : IApplicationBuilder) =
- let env = app.ApplicationServices.GetRequiredService()
+ let env = app.ApplicationServices.GetRequiredService ()
if env.IsDevelopment () then
- let _ = app.UseDeveloperExceptionPage ()
- ()
+ app.UseDeveloperExceptionPage ()
else
- let _ = app.UseGiraffeErrorHandler errorHandler
- ()
+ app.UseGiraffeErrorHandler errorHandler
+ |> ignore
+ let _ = app.UseForwardedHeaders ()
+ let _ = app.UseCanonicalDomains ()
let _ = app.UseStatusCodePagesWithReExecute "/error/{0}"
let _ = app.UseStaticFiles ()
let _ = app.UseCookiePolicy (CookiePolicyOptions (MinimumSameSitePolicy = SameSiteMode.Strict))
diff --git a/src/PrayerTracker/Email.fs b/src/PrayerTracker/Email.fs
index c559910..28d190a 100644
--- a/src/PrayerTracker/Email.fs
+++ b/src/PrayerTracker/Email.fs
@@ -30,23 +30,39 @@ type EmailOptions =
Strings : IStringLocalizer
}
-/// The e-mail address from which e-mail is sent
-let private fromAddress = "prayer@bitbadger.solutions"
+/// Options to use when sending e-mail
+type SmtpServerOptions() =
+ /// The hostname of the SMTP server
+ member val SmtpHost : string = "localhost" with get, set
-open MailKit.Security
-open Microsoft.Extensions.Configuration
+ /// The port over which SMTP communication should occur
+ member val Port : int = 25 with get, set
+
+ /// Whether to use SSL when communicating with the SMTP server
+ member val UseSsl : bool = false with get, set
+
+ /// The authentication to use with the SMTP server
+ member val Authentication : string = "" with get, set
+
+ /// The e-mail address from which messages should be sent
+ member val FromAddress : string = "prayer@bitbadger.solutions" with get, set
+
+
+/// The options for the SMTP server
+let smtpOptions = SmtpServerOptions ()
/// Get an SMTP client connection
-let getConnection (cfg : IConfiguration) = task {
+let getConnection () = task {
let client = new SmtpClient ()
- do! client.ConnectAsync (cfg.GetConnectionString "SmtpServer", 25, SecureSocketOptions.None)
+ do! client.ConnectAsync (smtpOptions.SmtpHost, smtpOptions.Port, smtpOptions.UseSsl)
+ do! client.AuthenticateAsync (smtpOptions.FromAddress, smtpOptions.Authentication)
return client
}
/// Create a mail message object, filled with everything but the body content
let createMessage opts =
let msg = new MimeMessage ()
- msg.From.Add (MailboxAddress (opts.Group.Preferences.EmailFromName, fromAddress))
+ msg.From.Add (MailboxAddress (opts.Group.Preferences.EmailFromName, smtpOptions.FromAddress))
msg.Subject <- opts.Subject
msg.ReplyTo.Add (MailboxAddress (opts.Group.Preferences.EmailFromName, opts.Group.Preferences.EmailFromAddress))
msg
diff --git a/src/PrayerTracker/PrayerRequest.fs b/src/PrayerTracker/PrayerRequest.fs
index 527ff15..732a228 100644
--- a/src/PrayerTracker/PrayerRequest.fs
+++ b/src/PrayerTracker/PrayerRequest.fs
@@ -88,7 +88,7 @@ let email date : HttpHandler = requireAccess [ User ] >=> fun next ctx -> task {
let! list = generateRequestList ctx listDate
let group = ctx.Session.CurrentGroup.Value
let! recipients = Members.forGroup group.Id
- use! client = Email.getConnection (ctx.GetService ())
+ use! client = Email.getConnection ()
do! Email.sendEmails
{ Client = client
Recipients = recipients
@@ -98,6 +98,7 @@ let email date : HttpHandler = requireAccess [ User ] >=> fun next ctx -> task {
PlainTextBody = list.AsText s
Strings = s
}
+ do! client.DisconnectAsync true
return!
viewInfo ctx
|> Views.PrayerRequest.email { list with Recipients = recipients }
diff --git a/src/PrayerTracker/PrayerTracker.fsproj b/src/PrayerTracker/PrayerTracker.fsproj
index 583871d..19dc847 100644
--- a/src/PrayerTracker/PrayerTracker.fsproj
+++ b/src/PrayerTracker/PrayerTracker.fsproj
@@ -24,6 +24,7 @@
+
diff --git a/src/PrayerTracker/SmallGroup.fs b/src/PrayerTracker/SmallGroup.fs
index 3629d55..6fe720a 100644
--- a/src/PrayerTracker/SmallGroup.fs
+++ b/src/PrayerTracker/SmallGroup.fs
@@ -269,7 +269,7 @@ let sendAnnouncement : HttpHandler = requireAccess [ User ] >=> validateCsrf >=>
return users |> List.map (fun u -> { Member.empty with Name = u.Name; Email = u.Email })
else return! Members.forGroup group.Id
}
- use! client = Email.getConnection (ctx.GetService ())
+ use! client = Email.getConnection ()
do! Email.sendEmails
{ Client = client
Recipients = recipients
@@ -280,6 +280,7 @@ let sendAnnouncement : HttpHandler = requireAccess [ User ] >=> validateCsrf >=>
PlainTextBody = plainText
Strings = s
}
+ do! client.DisconnectAsync true
// Add to the request list if desired
match model.SendToClass, model.AddToRequestList with
| "N", _