Skip to content

Commit

Permalink
Merge pull request #35 from IowaComputerGurus/feature/update-async
Browse files Browse the repository at this point in the history
Updates to support Async
  • Loading branch information
mitchelsellers authored Mar 21, 2024
2 parents 42e7cd2 + 485c475 commit b54c09c
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 325 deletions.
58 changes: 2 additions & 56 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,60 +34,6 @@ jobs:

- name: Restore Packages
run: dotnet restore "${{ env.solution-path }}"

- name: Build
run: dotnet build "${{ env.solution-path }}" --no-restore --configuration Release -p:version=${{ steps.gitversion.outputs.majorMinorPatch }}

code-quality:
if: github.actor != 'dependabot[bot]'
runs-on: windows-latest
name: Analyze Code Quality
env:
solution-path: './src/NetCore Utilities Email.sln'
steps:
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: 11
distribution: zulu
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Cache SonarCloud packages
uses: actions/[email protected]
with:
path: ~\sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache SonarCloud scanner
id: cache-sonar-scanner
uses: actions/[email protected]
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
restore-keys: ${{ runner.os }}-sonar-scanner
- name: Install SonarCloud scanner
if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
shell: powershell
run: |
New-Item -Path .\.sonar\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
- name: Install GitVersion
run: dotnet tool install --global GitVersion.Tool

- name: Determine Version
id: gitversion
uses: gittools/actions/gitversion/[email protected]
with:
useConfigFile: true

- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: |
.\.sonar\scanner\dotnet-sonarscanner begin /k:"IowaComputerGurus_netcore.utilities.email" /o:"iowacomputergurus-github" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io"
dotnet restore "${{ env.solution-path }}"
dotnet build "${{ env.solution-path }}" --no-restore --configuration Release -p:version=${{ steps.gitversion.outputs.majorMinorPatch }}
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
run: dotnet build "${{ env.solution-path }}" --no-restore --configuration Release -p:version=${{ steps.gitversion.outputs.majorMinorPatch }}
56 changes: 1 addition & 55 deletions .github/workflows/release-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,61 +5,7 @@ on:
tags:
- 'v*'

jobs:
code-quality:
runs-on: windows-latest
name: Analyze Code Quality
env:
solution-path: './src/NetCore Utilities Email.sln'
steps:
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: 11
distribution: zulu
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Cache SonarCloud packages
uses: actions/[email protected]
with:
path: ~\sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache SonarCloud scanner
id: cache-sonar-scanner
uses: actions/[email protected]
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
restore-keys: ${{ runner.os }}-sonar-scanner
- name: Install SonarCloud scanner
if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
shell: powershell
run: |
New-Item -Path .\.sonar\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
- name: Install GitVersion
run: dotnet tool install --global GitVersion.Tool

- name: Determine Version
id: gitversion
uses: gittools/actions/gitversion/[email protected]
with:
useConfigFile: true

- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: |
.\.sonar\scanner\dotnet-sonarscanner begin /k:"IowaComputerGurus_netcore.utilities.email" /o:"iowacomputergurus-github" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io"
dotnet restore "${{ env.solution-path }}"
dotnet build "${{ env.solution-path }}" --no-restore --configuration Release -p:version=${{ steps.gitversion.outputs.majorMinorPatch }}
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
jobs:
build:
runs-on: ubuntu-latest
name: Build & Publish to NuGet
Expand Down
2 changes: 1 addition & 1 deletion GitVersion.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mode: ContinuousDeployment
next-version: 5.1.4
next-version: 7.0.0
branches:
develop:
regex: develop
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

This is a base library to provide utilities for working with email in .NET 6. This project is used by more concrete implementations such as NetCore.Utilities.Email.Smtp.

## Usage
## Breaking Changes (Version 7.0)

Starting with version 7.0, all `IEmailService` methods have been converted to asynchronous operations.

## Installation
Standard installation via NuGet Package Manager
Expand Down
118 changes: 66 additions & 52 deletions src/NetCore.Utilities.Email/EmailTemplateFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,86 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;

namespace ICG.NetCore.Utilities.Email
namespace ICG.NetCore.Utilities.Email;

/// <summary>
/// Factory class for creating email content, using templates.
/// </summary>
public interface IEmailTemplateFactory
{
/// <summary>
/// Factory class for creating email content, using templates.
/// Creates HTML email content utilizing a template
/// </summary>
public interface IEmailTemplateFactory
/// <param name="subject">The desired subject of the email</param>
/// <param name="content">The desired content of the email, HTML formatted.</param>
/// <param name="preview">
/// An optional preview textual email content element, replaced in the template for more advanced
/// control
/// </param>
/// <param name="templateName">The name of the template to use, rather than the initial template.</param>
/// <returns>The updated content wrapped in the template</returns>
/// <exception cref="ArgumentNullException">Thrown for missing subject or content</exception>
/// <exception cref="ArgumentException">Thrown if requesting a template that is not defined</exception>
/// <exception cred="FileNotFoundException">Thrown if the defined template file does not exist</exception>
string BuildEmailContent(string subject, string content, string preview = "", string templateName = "");
}

/// <inheritdoc cref="IEmailTemplateFactory" />
public class EmailTemplateFactory : IEmailTemplateFactory
{
private readonly IHostEnvironment _hostingEnvironment;
private readonly IOptions<EmailTemplateSettings> _templateSettings;

/// <summary>
/// Default constructor with injected dependencies
/// </summary>
/// <param name="templateSettings"></param>
/// <param name="hostingEnvironment"></param>
public EmailTemplateFactory(IOptions<EmailTemplateSettings> templateSettings, IHostEnvironment hostingEnvironment)
{
/// <summary>
/// Creates HTML email content utilizing a template
/// </summary>
/// <param name="subject">The desired subject of the email</param>
/// <param name="content">The desired content of the email, HTML formatted.</param>
/// <param name="preview">
/// An optional preview textual email content element, replaced in the template for more advanced
/// control
/// </param>
/// <param name="templateName">The name of the template to use, rather than the initial template.</param>
/// <returns>The updated content wrapped in the template</returns>
/// <exception cref="ArgumentNullException">Thrown for missing subject or content</exception>
/// <exception cref="ArgumentException">Thrown if requesting a template that is not defined</exception>
/// <exception cred="FileNotFoundException">Thrown if the defined template file does not exist</exception>
string BuildEmailContent(string subject, string content, string preview = "", string templateName = "");
_templateSettings = templateSettings;
_hostingEnvironment = hostingEnvironment;
}


public class EmailTemplateFactory : IEmailTemplateFactory
/// <inheritdoc cref="IEmailTemplateFactory" />
public string BuildEmailContent(string subject, string content, string preview = "", string templateName = "")
{
private readonly IHostEnvironment _hostingEnvironment;
private readonly IOptions<EmailTemplateSettings> _templateSettings;
//Validate inputs
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentNullException(nameof(subject));
}

public EmailTemplateFactory(IOptions<EmailTemplateSettings> templateSettings,
IHostEnvironment hostingEnvironment)
if (string.IsNullOrEmpty(content))
{
_templateSettings = templateSettings;
_hostingEnvironment = hostingEnvironment;
throw new ArgumentNullException(nameof(content));
}

public string BuildEmailContent(string subject, string content, string preview = "", string templateName = "")
if (!string.IsNullOrEmpty(templateName) &&
!_templateSettings.Value.AdditionalTemplates.ContainsKey(templateName))
{
//Validate inputs
if (string.IsNullOrEmpty(subject))
throw new ArgumentNullException(nameof(subject));
if (string.IsNullOrEmpty(content))
throw new ArgumentNullException(nameof(content));
if (!string.IsNullOrEmpty(templateName) &&
!_templateSettings.Value.AdditionalTemplates.ContainsKey(templateName))
throw new ArgumentException($"Requested template {templateName} was not found in configuration",
nameof(templateName));
throw new ArgumentException($"Requested template {templateName} was not found in configuration",
nameof(templateName));
}

//Get the template
var templatePath = string.IsNullOrEmpty(templateName)
? _templateSettings.Value.DefaultTemplatePath
: _templateSettings.Value.AdditionalTemplates[templateName];
var fullTemplatePath = Path.Combine(_hostingEnvironment.ContentRootPath, templatePath);
if (!File.Exists(fullTemplatePath))
throw new FileNotFoundException("Unable to find template file", fullTemplatePath);
//Get the template
var templatePath = string.IsNullOrEmpty(templateName)
? _templateSettings.Value.DefaultTemplatePath
: _templateSettings.Value.AdditionalTemplates[templateName];
var fullTemplatePath = Path.Combine(_hostingEnvironment.ContentRootPath, templatePath);
if (!File.Exists(fullTemplatePath))
{
throw new FileNotFoundException("Unable to find template file", fullTemplatePath);
}

//Replace the content
var templateBuilder =
new StringBuilder(File.ReadAllText(Path.Combine(_hostingEnvironment.ContentRootPath, templatePath)));
templateBuilder.Replace("[SUBJECT]", subject);
templateBuilder.Replace("[PREVIEW]", preview);
templateBuilder.Replace("[CONTENT]", content);
//Replace the content
var templateBuilder =
new StringBuilder(File.ReadAllText(fullTemplatePath));
templateBuilder.Replace("[SUBJECT]", subject);
templateBuilder.Replace("[PREVIEW]", preview);
templateBuilder.Replace("[CONTENT]", content);

//Return message content
return templateBuilder.ToString();
}
//Return message content
return templateBuilder.ToString();
}
}
21 changes: 15 additions & 6 deletions src/NetCore.Utilities.Email/EmailTemplateSettings.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
using System.Collections.Generic;

namespace ICG.NetCore.Utilities.Email
namespace ICG.NetCore.Utilities.Email;

/// <summary>
/// Setting object for email templates
/// </summary>
public class EmailTemplateSettings
{
public class EmailTemplateSettings
{
public string DefaultTemplatePath { get; set; }
public Dictionary<string, string> AdditionalTemplates { get; set; }
}
/// <summary>
/// The application relative file path to the default template file
/// </summary>
public string DefaultTemplatePath { get; set; }

/// <summary>
/// A collection of additional templates with a "name" and "path" for each one
/// </summary>
public Dictionary<string, string> AdditionalTemplates { get; set; }
}
Loading

0 comments on commit b54c09c

Please sign in to comment.