From 30364c7a29d48c6172cbe05495d751d157f6b860 Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Wed, 20 Mar 2024 22:36:48 -0500 Subject: [PATCH 1/6] Fixes #34 --- .github/workflows/ci-build.yml | 61 +--- .github/workflows/release-build.yml | 56 +--- GitVersion.yml | 2 +- README.md | 4 +- .../EmailTemplateFactory.cs | 118 +++---- .../EmailTemplateSettings.cs | 21 +- src/NetCore.Utilities.Email/IEmailService.cs | 317 +++++++++--------- 7 files changed, 254 insertions(+), 325 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 5275651..62c6a74 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -34,60 +34,19 @@ 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/cache@v3.3.2 - with: - path: ~\sonar\cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - name: Cache SonarCloud scanner - id: cache-sonar-scanner - uses: actions/cache@v3.3.2 - 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/execute@v0.10.2 - with: - useConfigFile: true + - name: Test + run: dotnet test "${{ env.solution-path }}" --no-build --configuration Release --collect "XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover --logger "trx;LogFileName=unittests.trx" - - name: Build and analyze + - name: Push Coverage to Codacy + shell: bash env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - shell: powershell + CODACY_ORGANIZATION_PROVIDER: ${{ secrets.CODACY_ORGANIZATION_PROVIDER }} + CODACY_USERNAME: ${{ secrets.CODACY_USERNAME }} + CODACY_PROJECT_NAME: ${{ secrets.CODACY_PROJECT_NAME }} + CODACY_API_TOKEN: ${{ secrets.CODACY_API_TOKEN }} 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 }}" + bash <(curl -Ls https://coverage.codacy.com/get.sh) report $(find . -name '*.opencover.xml' -printf '-r %p ') \ No newline at end of file diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index f5f0033..8db2b69 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -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/cache@v3.3.2 - with: - path: ~\sonar\cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - name: Cache SonarCloud scanner - id: cache-sonar-scanner - uses: actions/cache@v3.3.2 - 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/execute@v0.10.2 - 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 diff --git a/GitVersion.yml b/GitVersion.yml index a59d151..8b402e5 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,5 +1,5 @@ mode: ContinuousDeployment -next-version: 5.1.4 +next-version: 7.0.0 branches: develop: regex: develop diff --git a/README.md b/README.md index f097463..c5ba7cc 100644 --- a/README.md +++ b/README.md @@ -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 were converted to Async! ## Installation Standard installation via NuGet Package Manager diff --git a/src/NetCore.Utilities.Email/EmailTemplateFactory.cs b/src/NetCore.Utilities.Email/EmailTemplateFactory.cs index 448f777..1c39c75 100644 --- a/src/NetCore.Utilities.Email/EmailTemplateFactory.cs +++ b/src/NetCore.Utilities.Email/EmailTemplateFactory.cs @@ -4,72 +4,76 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; -namespace ICG.NetCore.Utilities.Email +namespace ICG.NetCore.Utilities.Email; + +/// +/// Factory class for creating email content, using templates. +/// +public interface IEmailTemplateFactory { /// - /// Factory class for creating email content, using templates. + /// Creates HTML email content utilizing a template /// - public interface IEmailTemplateFactory - { - /// - /// Creates HTML email content utilizing a template - /// - /// The desired subject of the email - /// The desired content of the email, HTML formatted. - /// - /// An optional preview textual email content element, replaced in the template for more advanced - /// control - /// - /// The name of the template to use, rather than the initial template. - /// The updated content wrapped in the template - /// Thrown for missing subject or content - /// Thrown if requesting a template that is not defined - /// Thrown if the defined template file does not exist - string BuildEmailContent(string subject, string content, string preview = "", string templateName = ""); - } + /// The desired subject of the email + /// The desired content of the email, HTML formatted. + /// + /// An optional preview textual email content element, replaced in the template for more advanced + /// control + /// + /// The name of the template to use, rather than the initial template. + /// The updated content wrapped in the template + /// Thrown for missing subject or content + /// Thrown if requesting a template that is not defined + /// Thrown if the defined template file does not exist + string BuildEmailContent(string subject, string content, string preview = "", string templateName = ""); +} +/// +public class EmailTemplateFactory : IEmailTemplateFactory +{ + private readonly IHostEnvironment _hostingEnvironment; + private readonly IOptions _templateSettings; - public class EmailTemplateFactory : IEmailTemplateFactory + /// + /// Default constructor with injected dependencies + /// + /// + /// + public EmailTemplateFactory(IOptions templateSettings, IHostEnvironment hostingEnvironment) { - private readonly IHostEnvironment _hostingEnvironment; - private readonly IOptions _templateSettings; - - public EmailTemplateFactory(IOptions templateSettings, - IHostEnvironment hostingEnvironment) - { - _templateSettings = templateSettings; - _hostingEnvironment = hostingEnvironment; - } + _templateSettings = templateSettings; + _hostingEnvironment = hostingEnvironment; + } - public string BuildEmailContent(string subject, string content, string preview = "", string 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)); + /// + public string BuildEmailContent(string subject, string content, string preview = "", string 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)); - //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(); } } \ No newline at end of file diff --git a/src/NetCore.Utilities.Email/EmailTemplateSettings.cs b/src/NetCore.Utilities.Email/EmailTemplateSettings.cs index a1f7a44..a5639d1 100644 --- a/src/NetCore.Utilities.Email/EmailTemplateSettings.cs +++ b/src/NetCore.Utilities.Email/EmailTemplateSettings.cs @@ -1,10 +1,19 @@ using System.Collections.Generic; -namespace ICG.NetCore.Utilities.Email +namespace ICG.NetCore.Utilities.Email; + +/// +/// Setting object for email templates +/// +public class EmailTemplateSettings { - public class EmailTemplateSettings - { - public string DefaultTemplatePath { get; set; } - public Dictionary AdditionalTemplates { get; set; } - } + /// + /// The application relative file path to the default template file + /// + public string DefaultTemplatePath { get; set; } + + /// + /// A collection of additional templates with a "name" and "path" for each one + /// + public Dictionary AdditionalTemplates { get; set; } } \ No newline at end of file diff --git a/src/NetCore.Utilities.Email/IEmailService.cs b/src/NetCore.Utilities.Email/IEmailService.cs index 5044dec..c953fe8 100644 --- a/src/NetCore.Utilities.Email/IEmailService.cs +++ b/src/NetCore.Utilities.Email/IEmailService.cs @@ -1,160 +1,169 @@ using System.Collections.Generic; +using System.Threading.Tasks; -namespace ICG.NetCore.Utilities.Email +namespace ICG.NetCore.Utilities.Email; + +/// +/// Represents a service that can deliver email messages to the recipients. This is utilized by all downstream +/// implementations of ICG.NetCore.Utilities.Email applications allowing easy switching between providers & options. +/// +public interface IEmailService { /// - /// Represents a service that can deliver email messages to the recipients. This is utilized by all downstream - /// implementations of ICG.NetCore.Utilities.Email applications allowing easy switching between providers & options. + /// Returns the configured administrator email for the service + /// + string AdminEmail { get; } + + /// + /// Returns the configured administrator name for outbound emails + /// + string AdminName { get; } + + /// + /// Shortcut for sending an email to the administrator, only requiring the subject and body. + /// + /// The message subject + /// The message body + Task SendMessageToAdministratorAsync(string subject, string bodyHtml); + + /// + /// Sends a message to the administrator as well as the additional contacts provided. + /// + /// Additional email addresses to add to the CC line + /// The email subject + /// The HTML content of the email + Task SendMessageToAdministratorAsync(IEnumerable ccAddressList, string subject, string bodyHtml); + + /// + /// Sends a message to the specified recipient, with the supplied subject and body + /// + /// Who is receiving the email + /// The message subject + /// The message body + Task SendMessageAsync(string toAddress, string subject, string bodyHtml); + + /// + /// Sends a message to the specified recipient, with the supplied subject and body + /// + /// Who is receiving the email + /// The message subject + /// The message body + /// A list of tokens that should be replaced within the email message + Task SendMessageAsync(string toAddress, string subject, string bodyHtml, + List> tokens); + + /// + /// Sends a message to the specified recipient, with the supplied subject and body + /// + /// Who is receiving the email + /// Additional CC'ed emails + /// The message subject + /// The message body + Task SendMessageAsync(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml); + + /// + /// Sends a message to the specified recipient, with the supplied subject and body + /// + /// Who is receiving the email + /// Additional CC'ed emails + /// The message subject + /// The message body + /// A list of tokens that should be replaced within the email message + Task SendMessageAsync(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, + List> tokens); + + /// + /// Sends a message to the specified recipient, and CC's with the supplied subject and body + /// + /// Who is receiving the email + /// Additional CC'ed emails + /// The message subject + /// The message body + /// A list of tokens that should be replaced within the email message + /// The optional custom template to override with + /// The a custom key for identifying a sender + Task SendMessageAsync(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, + List> tokens, + string templateName, string senderKeyName = ""); + + /// + /// Sends a message to the specified recipient, with the supplied subject and body + /// + /// The address to be used as a reply to + /// The address to be used as a reply to + /// Who is receiving the email + /// The message subject + /// The message body + Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, string subject, + string bodyHtml); + + /// + /// Sends a message to the specified recipient, with the supplied subject and body + /// + /// The address to be used as a reply to + /// The address to be used as a reply to + /// Who is receiving the email + /// The message subject + /// The message body + /// A list of tokens that should be replaced within the email message + Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, string subject, + string bodyHtml, List> tokens); + + /// + /// Sends a message to the specified recipient, with the supplied subject and body + /// + /// The address to be used as a reply to + /// The address to be used as a reply to + /// Who is receiving the email + /// Additional CC'ed emails + /// The message subject + /// The message body + Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, + IEnumerable ccAddressList, string subject, string bodyHtml); + + /// + /// Sends a message to the specified recipient, with the supplied subject and body + /// + /// The address to be used as a reply to + /// The address to be used as a reply to + /// Who is receiving the email + /// Additional CC'ed emails + /// The message subject + /// The message body + /// A list of tokens that should be replaced within the email message + Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, + IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens); + + /// + /// Sends a message to the specified recipient, and CC's with the supplied subject and body + /// + /// The address to be used as a reply to + /// The address to be used as a reply to + /// Who is receiving the email + /// Additional CC'ed emails + /// The message subject + /// The message body + /// A list of tokens that should be replaced within the email message + /// The optional custom template to override with + /// The a custom key for identifying a sender + Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, + IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens, + string templateName, string senderKeyName = ""); + + /// + /// Creates a message with an attachment /// - public interface IEmailService - { - /// - /// Returns the configured administrator email for the service - /// - string AdminEmail { get; } - - /// - /// Returns the configured administrator name for outbound emails - /// - string AdminName { get; } - - /// - /// Shortcut for sending an email to the administrator, only requiring the subject and body. - /// - /// The message subject - /// The message body - bool SendMessageToAdministrator(string subject, string bodyHtml); - - /// - /// Sends a message to the administrator as well as the additional contacts provided. - /// - /// Additional email addresses to add to the CC line - /// The email subject - /// The HTML content of the email - bool SendMessageToAdministrator(IEnumerable ccAddressList, string subject, string bodyHtml); - - /// - /// Sends a message to the specified recipient, with the supplied subject and body - /// - /// Who is receiving the email - /// The message subject - /// The message body - bool SendMessage(string toAddress, string subject, string bodyHtml); - - /// - /// Sends a message to the specified recipient, with the supplied subject and body - /// - /// Who is receiving the email - /// The message subject - /// The message body - /// A list of tokens that should be replaced within the email message - bool SendMessage(string toAddress, string subject, string bodyHtml, List> tokens); - - /// - /// Sends a message to the specified recipient, with the supplied subject and body - /// - /// Who is receiving the email - /// Additional CC'ed emails - /// The message subject - /// The message body - bool SendMessage(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml); - - /// - /// Sends a message to the specified recipient, with the supplied subject and body - /// - /// Who is receiving the email - /// Additional CC'ed emails - /// The message subject - /// The message body - /// A list of tokens that should be replaced within the email message - bool SendMessage(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens); - - /// - /// Sends a message to the specified recipient, and CC's with the supplied subject and body - /// - /// Who is receiving the email - /// Additional CC'ed emails - /// The message subject - /// The message body - /// A list of tokens that should be replaced within the email message - /// The optional custom template to override with - /// The a custom key for identifying a sender - bool SendMessage(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens, - string templateName, string senderKeyName = ""); - - /// - /// Sends a message to the specified recipient, with the supplied subject and body - /// - /// The address to be used as a reply to - /// The address to be used as a reply to - /// Who is receiving the email - /// The message subject - /// The message body - bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, string subject, string bodyHtml); - - /// - /// Sends a message to the specified recipient, with the supplied subject and body - /// - /// The address to be used as a reply to - /// The address to be used as a reply to - /// Who is receiving the email - /// The message subject - /// The message body - /// A list of tokens that should be replaced within the email message - bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, string subject, string bodyHtml, List> tokens); - - /// - /// Sends a message to the specified recipient, with the supplied subject and body - /// - /// The address to be used as a reply to - /// The address to be used as a reply to - /// Who is receiving the email - /// Additional CC'ed emails - /// The message subject - /// The message body - bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml); - - /// - /// Sends a message to the specified recipient, with the supplied subject and body - /// - /// The address to be used as a reply to - /// The address to be used as a reply to - /// Who is receiving the email - /// Additional CC'ed emails - /// The message subject - /// The message body - /// A list of tokens that should be replaced within the email message - bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens); - - /// - /// Sends a message to the specified recipient, and CC's with the supplied subject and body - /// - /// The address to be used as a reply to - /// The address to be used as a reply to - /// Who is receiving the email - /// Additional CC'ed emails - /// The message subject - /// The message body - /// A list of tokens that should be replaced within the email message - /// The optional custom template to override with - /// The a custom key for identifying a sender - bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens, - string templateName, string senderKeyName = ""); - - /// - /// Creates a message with an attachment - /// - /// The to address for the message - /// The address(ses) to add a CC's - /// The subject of the message - /// Attachment Content - /// Attachment file name - /// The HTML body contents - /// A list of tokens that should be replaced within the email message - /// The optional custom template to override with - /// The a custom key for identifying a sender - /// - bool SendMessageWithAttachment(string toAddress, IEnumerable ccAddressList, string subject, - byte[] fileContent, string fileName, string bodyHtml, List> tokens, string templateName = "", string senderKeyName = ""); - } + /// The to address for the message + /// The address(ses) to add a CC's + /// The subject of the message + /// Attachment Content + /// Attachment file name + /// The HTML body contents + /// A list of tokens that should be replaced within the email message + /// The optional custom template to override with + /// The a custom key for identifying a sender + /// + Task SendMessageWithAttachmentAsync(string toAddress, IEnumerable ccAddressList, string subject, + byte[] fileContent, string fileName, string bodyHtml, List> tokens, + string templateName = "", string senderKeyName = ""); } \ No newline at end of file From 1151fa7161ad533a75813bff0587ec6df7c57c37 Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Wed, 20 Mar 2024 22:38:34 -0500 Subject: [PATCH 2/6] Fixes --- .github/workflows/ci-build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 62c6a74..176930d 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -42,11 +42,11 @@ jobs: run: dotnet test "${{ env.solution-path }}" --no-build --configuration Release --collect "XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover --logger "trx;LogFileName=unittests.trx" - name: Push Coverage to Codacy - shell: bash - env: - CODACY_ORGANIZATION_PROVIDER: ${{ secrets.CODACY_ORGANIZATION_PROVIDER }} - CODACY_USERNAME: ${{ secrets.CODACY_USERNAME }} - CODACY_PROJECT_NAME: ${{ secrets.CODACY_PROJECT_NAME }} - CODACY_API_TOKEN: ${{ secrets.CODACY_API_TOKEN }} - run: | - bash <(curl -Ls https://coverage.codacy.com/get.sh) report $(find . -name '*.opencover.xml' -printf '-r %p ') \ No newline at end of file + shell: bash + env: + CODACY_ORGANIZATION_PROVIDER: ${{ secrets.CODACY_ORGANIZATION_PROVIDER }} + CODACY_USERNAME: ${{ secrets.CODACY_USERNAME }} + CODACY_PROJECT_NAME: ${{ secrets.CODACY_PROJECT_NAME }} + CODACY_API_TOKEN: ${{ secrets.CODACY_API_TOKEN }} + run: | + bash <(curl -Ls https://coverage.codacy.com/get.sh) report $(find . -name '*.opencover.xml' -printf '-r %p ') \ No newline at end of file From 6612cdd1f64df88caaa0e9424546acb6310715b9 Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Wed, 20 Mar 2024 22:40:01 -0500 Subject: [PATCH 3/6] Disable unit test --- .github/workflows/ci-build.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 176930d..fe66d0b 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -38,9 +38,6 @@ jobs: - name: Build run: dotnet build "${{ env.solution-path }}" --no-restore --configuration Release -p:version=${{ steps.gitversion.outputs.majorMinorPatch }} - - name: Test - run: dotnet test "${{ env.solution-path }}" --no-build --configuration Release --collect "XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover --logger "trx;LogFileName=unittests.trx" - - name: Push Coverage to Codacy shell: bash env: From 76114fb338eb726a3676733a20c12c4e4706a2e3 Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Wed, 20 Mar 2024 22:42:24 -0500 Subject: [PATCH 4/6] One more edit --- .github/workflows/ci-build.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index fe66d0b..c874e74 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -36,14 +36,4 @@ jobs: run: dotnet restore "${{ env.solution-path }}" - name: Build - run: dotnet build "${{ env.solution-path }}" --no-restore --configuration Release -p:version=${{ steps.gitversion.outputs.majorMinorPatch }} - - - name: Push Coverage to Codacy - shell: bash - env: - CODACY_ORGANIZATION_PROVIDER: ${{ secrets.CODACY_ORGANIZATION_PROVIDER }} - CODACY_USERNAME: ${{ secrets.CODACY_USERNAME }} - CODACY_PROJECT_NAME: ${{ secrets.CODACY_PROJECT_NAME }} - CODACY_API_TOKEN: ${{ secrets.CODACY_API_TOKEN }} - run: | - bash <(curl -Ls https://coverage.codacy.com/get.sh) report $(find . -name '*.opencover.xml' -printf '-r %p ') \ No newline at end of file + run: dotnet build "${{ env.solution-path }}" --no-restore --configuration Release -p:version=${{ steps.gitversion.outputs.majorMinorPatch }} \ No newline at end of file From 97c06bd55128dee2a82f863b99da07b537b1100e Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Wed, 20 Mar 2024 22:47:13 -0500 Subject: [PATCH 5/6] Make Codacity happy --- src/NetCore.Utilities.Email/EmailTemplateFactory.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/NetCore.Utilities.Email/EmailTemplateFactory.cs b/src/NetCore.Utilities.Email/EmailTemplateFactory.cs index 1c39c75..f7a819a 100644 --- a/src/NetCore.Utilities.Email/EmailTemplateFactory.cs +++ b/src/NetCore.Utilities.Email/EmailTemplateFactory.cs @@ -50,13 +50,21 @@ public string BuildEmailContent(string subject, string content, string preview = { //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)); + } //Get the template var templatePath = string.IsNullOrEmpty(templateName) @@ -64,7 +72,9 @@ public string BuildEmailContent(string subject, string content, string preview = : _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 = From 485c47575e1359cef6aaeb129a100caec52f5954 Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Wed, 20 Mar 2024 22:48:20 -0500 Subject: [PATCH 6/6] Update README.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c5ba7cc..f6746d4 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This is a base library to provide utilities for working with email in .NET 6. T ## Breaking Changes (Version 7.0) -Starting with version 7.0, all `IEmailService` methods were converted to Async! +Starting with version 7.0, all `IEmailService` methods have been converted to asynchronous operations. ## Installation Standard installation via NuGet Package Manager