From 41c3904e85fe4e416e2bb6c8886951fc384958e9 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sun, 9 Jul 2023 23:08:10 -0400 Subject: [PATCH] Upgrade e-mail config --- src/Dockerfile | 1 + src/JobsJobsJobs/Application/App.fs | 3 ++ src/JobsJobsJobs/Common/Email.fs | 53 ++++++++++++++++++++------ src/JobsJobsJobs/Directory.Build.props | 4 +- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/Dockerfile b/src/Dockerfile index b4fe45f..a7a1967 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -14,6 +14,7 @@ RUN dotnet restore COPY . ./ WORKDIR /jjj/JobsJobsJobs/Application RUN dotnet publish -c Release -r linux-x64 +RUN rm bin/Release/net7.0/linux-x64/publish/appsettings.*.json FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine as final WORKDIR /app diff --git a/src/JobsJobsJobs/Application/App.fs b/src/JobsJobsJobs/Application/App.fs index af1d2e2..a8a857c 100644 --- a/src/JobsJobsJobs/Application/App.fs +++ b/src/JobsJobsJobs/Application/App.fs @@ -59,6 +59,9 @@ let main args = opts.Cookie.HttpOnly <- true opts.Cookie.IsEssential <- true) + let emailCfg = cfg.GetSection "Email" + if (emailCfg.GetChildren >> Seq.isEmpty >> not) () then ConfigurationBinder.Bind(emailCfg, Email.options) + let app = builder.Build () // Unify the endpoints from all features diff --git a/src/JobsJobsJobs/Common/Email.fs b/src/JobsJobsJobs/Common/Email.fs index b8df062..ce764ad 100644 --- a/src/JobsJobsJobs/Common/Email.fs +++ b/src/JobsJobsJobs/Common/Email.fs @@ -3,17 +3,41 @@ module JobsJobsJobs.Email open System.Net open JobsJobsJobs.Domain open MailKit.Net.Smtp -open MailKit.Security open MimeKit +/// Options to use when sending e-mail +type EmailOptions() = + /// The hostname of the SMTP server + member val SmtpHost : string = "localhost" with get, set + + /// 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 = "nobody@noagendacareers.com" with get, set + + /// The name from which messages should be sent + member val FromName : string = "Jobs, Jobs, Jobs" with get, set + + +/// The options for the SMTP server +let mutable options = EmailOptions () + /// Private functions for sending e-mail [] module private Helpers = /// Create an SMTP client - let smtpClient () = backgroundTask { + let createClient () = backgroundTask { let client = new SmtpClient () - do! client.ConnectAsync ("localhost", 25, SecureSocketOptions.None) + do! client.ConnectAsync (options.SmtpHost, options.Port, options.UseSsl) + do! client.AuthenticateAsync (options.FromAddress, options.Authentication) return client } @@ -24,13 +48,19 @@ module private Helpers = msg.To.Add (MailboxAddress (Citizen.name citizen, citizen.Email)) msg.Subject <- subject msg - + + /// Send a message + let sendMessage msg = backgroundTask { + use! client = createClient () + let! result = client.SendAsync msg + do! client.DisconnectAsync true + return result + } /// Send an account confirmation e-mail let sendAccountConfirmation citizen security = backgroundTask { - let token = WebUtility.UrlEncode security.Token.Value - use! client = smtpClient () - use msg = createMessage citizen "Account Confirmation Request" + let token = WebUtility.UrlEncode security.Token.Value + use msg = createMessage citizen "Account Confirmation Request" let text = [ $"ITM, {Citizen.name citizen}!" @@ -57,14 +87,13 @@ let sendAccountConfirmation citizen security = backgroundTask { use msgText = new TextPart (Text = text) msg.Body <- msgText - return! client.SendAsync msg + return! sendMessage msg } /// Send a password reset link let sendPasswordReset citizen security = backgroundTask { - let token = WebUtility.UrlEncode security.Token.Value - use! client = smtpClient () - use msg = createMessage citizen "Reset Password for Jobs, Jobs, Jobs" + let token = WebUtility.UrlEncode security.Token.Value + use msg = createMessage citizen "Reset Password for Jobs, Jobs, Jobs" let text = [ $"ITM, {Citizen.name citizen}!" @@ -90,5 +119,5 @@ let sendPasswordReset citizen security = backgroundTask { use msgText = new TextPart (Text = text) msg.Body <- msgText - return! client.SendAsync msg + return! sendMessage msg } diff --git a/src/JobsJobsJobs/Directory.Build.props b/src/JobsJobsJobs/Directory.Build.props index 7df57c2..b08fafe 100644 --- a/src/JobsJobsJobs/Directory.Build.props +++ b/src/JobsJobsJobs/Directory.Build.props @@ -4,7 +4,7 @@ enable embedded false - 3.1.1.0 - 3.1.1.0 + 3.1.2.0 + 3.1.2.0