diff --git a/.github/workflows/SendEmail_build_and_test_on_main.yml b/.github/workflows/SendEmail_build_and_test_on_main.yml new file mode 100644 index 0000000..e9db8f3 --- /dev/null +++ b/.github/workflows/SendEmail_build_and_test_on_main.yml @@ -0,0 +1,26 @@ +name: SendEmail_build_main + +on: + push: + branches: + - main + paths: + - 'Frends.SMTP.SendEmail/**' + workflow_dispatch: + +jobs: + build: + uses: FrendsPlatform/FrendsTasks/.github/workflows/build_main.yml@main + with: + env_var_name_1: Frends_SMTP_Username + env_var_name_2: FRENDS_SMTP_PASSWORD + env_var_name_3: Frends_SMTP_Address + env_var_name_4: Frends_SMTP_Email + workdir: Frends.SMTP.SendEmail + secrets: + env_var_value_1: ${{ secrets.FRENDS_SMTP_USERNAME }} + env_var_value_2: ${{ secrets.FRENDS_SMTP_PASSWORD }} + env_var_value_3: ${{ secrets.FRENDS_SMTP_ADDRESS }} + env_var_value_4: ${{ secrets.FRENDS_SMTP_EMAIL }} + badge_service_api_key: ${{ secrets.BADGE_SERVICE_API_KEY }} + \ No newline at end of file diff --git a/.github/workflows/SendEmail_build_and_test_on_push.yml b/.github/workflows/SendEmail_build_and_test_on_push.yml new file mode 100644 index 0000000..5e7d6b5 --- /dev/null +++ b/.github/workflows/SendEmail_build_and_test_on_push.yml @@ -0,0 +1,27 @@ +name: SendEmail_build_test + +on: + push: + branches-ignore: + - main + paths: + - 'Frends.SMTP.SendEmail/**' + workflow_dispatch: + +jobs: + build: + uses: FrendsPlatform/FrendsTasks/.github/workflows/build_test.yml@main + with: + env_var_name_1: Frends_SMTP_Username + env_var_name_2: FRENDS_SMTP_PASSWORD + env_var_name_3: Frends_SMTP_Address + env_var_name_4: Frends_SMTP_Email + workdir: Frends.SMTP.SendEmail + secrets: + env_var_value_1: ${{ secrets.FRENDS_SMTP_USERNAME }} + env_var_value_2: ${{ secrets.FRENDS_SMTP_PASSWORD }} + env_var_value_3: ${{ secrets.FRENDS_SMTP_ADDRESS }} + env_var_value_4: ${{ secrets.FRENDS_SMTP_EMAIL }} + badge_service_api_key: ${{ secrets.BADGE_SERVICE_API_KEY }} + test_feed_api_key: ${{ secrets.TASKS_TEST_FEED_API_KEY }} + diff --git a/.github/workflows/SendEmail_dev.yml b/.github/workflows/SendEmail_dev.yml deleted file mode 100644 index 68c95c8..0000000 --- a/.github/workflows/SendEmail_dev.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Frends.SMTP.SendEmail Test - -on: - push: - branches-ignore: - - main - paths: - - 'Frends.SMTP.SendEmail/**' - - 'Frends.SMTP.SendEmail.Tests/**' - workflow_dispatch: - pull_request: - -jobs: - build: - uses: FrendsPlatform/FrendsTasks/.github/workflows/build_test.yml@main - with: - env_var_name_1: SMTP_PASSWORD - workdir: Frends.SMTP.SendEmail - secrets: - env_var_value_1: ${{ secrets.SMTP_PASSWORD }} - badge_service_api_key: ${{ secrets.BADGE_SERVICE_API_KEY }} - test_feed_api_key: ${{ secrets.TASKS_TEST_FEED_API_KEY }} - diff --git a/.github/workflows/SendEmail_main.yml b/.github/workflows/SendEmail_main.yml deleted file mode 100644 index d5cca30..0000000 --- a/.github/workflows/SendEmail_main.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Frends.SMTP.SendEmail Main - -on: - push: - branches: - - main - paths: - - 'Frends.SMTP.SendEmail/**' - - 'Frends.SMTP.SendEmail.Tests/**' - workflow_dispatch: - - -jobs: - build: - uses: FrendsPlatform/FrendsTasks/.github/workflows/build_main.yml@main - with: - env_var_name_1: SMTP_PASSWORD - workdir: Frends.SMTP.SendEmail - secrets: - env_var_value_1: ${{ secrets.SMTP_PASSWORD }} - badge_service_api_key: ${{ secrets.BADGE_SERVICE_API_KEY }} - \ No newline at end of file diff --git a/.github/workflows/SendEmail_release.yml b/.github/workflows/SendEmail_release.yml index 8cf9d63..cfbc64c 100644 --- a/.github/workflows/SendEmail_release.yml +++ b/.github/workflows/SendEmail_release.yml @@ -1,8 +1,7 @@ -name: Frends.SMTP.SendEmail Release +name: SendEmail_release on: - workflow_dispatch: - + workflow_dispatch: jobs: build: diff --git a/Frends.SMTP.SendEmail/CHANGELOG.md b/Frends.SMTP.SendEmail/CHANGELOG.md index deb4c20..d3eb860 100644 --- a/Frends.SMTP.SendEmail/CHANGELOG.md +++ b/Frends.SMTP.SendEmail/CHANGELOG.md @@ -1,11 +1,19 @@ # Changelog + +## [1.1.0] - 2023-11-29 +### Fixed +- [Breaking] Fixed issue with the attachments can't be given as expression by adding AttachmentOptions class. + ## [1.0.3] - 2023-11-03 +### Added - Fix missing XML comments. ## [1.0.2] - 2023-11-03 +### Added - Fix bug #20 - Missing Frends tasks metadata file ## [1.0.1] - 2023-05-15 +### Fixed - Fix bug #14 - NullReferenceException when field with 'Expression' type is empty ## [1.0.0] - 2022-02-09 diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.Tests/SendEmailTests.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.Tests/SendEmailTests.cs index 757f5c1..a452b6e 100644 --- a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.Tests/SendEmailTests.cs +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.Tests/SendEmailTests.cs @@ -1,201 +1,197 @@ using NUnit.Framework; using System; using System.IO; +using Frends.SMTP.SendEmail.Definitions; -namespace Frends.SMTP.SendEmail.Tests +namespace Frends.SMTP.SendEmail.Tests; + +[TestFixture] +public class SendEmailTests { - /// - /// NOTE: To run these unit tests, you need an SMTP test server. Fill in the properties below with your values. - /// - [TestFixture] - public class SendEmailTests + // ****************************************** FILL THESE ****************************************************** + private static readonly string USERNAME = Environment.GetEnvironmentVariable("Frends_SMTP_Username"); + private static readonly string PASSWORD = Environment.GetEnvironmentVariable("Frends_SMTP_Password"); + private static readonly string SMTPADDRESS = Environment.GetEnvironmentVariable("Frends_SMTP_Address"); + private static readonly string TOEMAILADDRESS = Environment.GetEnvironmentVariable("Frends_SMTP_Email"); + private static readonly string FROMEMAILADDRESS = Environment.GetEnvironmentVariable("Frends_SMTP_Email"); + private const int PORT = 587; + private const bool USESSL = true; + private const bool USEWINDOWSAUTHENTICATION = false; + // ************************************************************************************************************ + + + private const string TEMP_ATTACHMENT_SOURCE = "emailtestattachments"; + private const string TEST_FILE_NAME = "testattachment.txt"; + private const string TEST_FILE_NOT_EXISTING = "doesntexist.txt"; + + private string _localAttachmentFolder; + private string _filepath; + private Input _input; + private Input _input2; + private Options _options; + + [SetUp] + public void EmailTestSetup() { - // ****************************************** FILL THESE ****************************************************** - private const string USERNAME = "apikey"; - private const string PASSWORD = ""; - private const string SMTPADDRESS = "smtp.sendgrid.net"; - private const string TOEMAILADDRESS = "jefim.borissov@hiq.fi"; - private const string FROMEMAILADDRESS = "jefim.borissov@hiq.fi"; - private const int PORT = 587; - private const bool USESSL = true; - private const bool USEWINDOWSAUTHENTICATION = false; - // ************************************************************************************************************ - - - private const string TEMP_ATTACHMENT_SOURCE = "emailtestattachments"; - private const string TEST_FILE_NAME = "testattachment.txt"; - private const string TEST_FILE_NOT_EXISTING = "doesntexist.txt"; - - private string _localAttachmentFolder; - private string _filepath; - private Input _input; - private Input _input2; - private Options _options; - - [SetUp] - public void EmailTestSetup() - { - _localAttachmentFolder = Path.Combine(Path.GetTempPath(), TEMP_ATTACHMENT_SOURCE); - - if (!Directory.Exists(_localAttachmentFolder)) - Directory.CreateDirectory(_localAttachmentFolder); - - _filepath = Path.Combine(_localAttachmentFolder, TEST_FILE_NAME); - - if (!File.Exists(_filepath)) - { - File.Create(_filepath).Dispose(); - } - - _input = new Input() - { - From = FROMEMAILADDRESS, - To = TOEMAILADDRESS, - Cc = "", - Bcc = "", - Message = "testmsg", - IsMessageHtml = false, - SenderName = "EmailTestSender", - MessageEncoding = "utf-8" - }; - - _input2 = new Input() - { - From = FROMEMAILADDRESS, - To = TOEMAILADDRESS, - Cc = null, - Bcc = null, - Message = "testmsg", - IsMessageHtml = false, - SenderName = "EmailTestSender", - MessageEncoding = "utf-8" - }; - - var passwordFromEnvironment = Environment.GetEnvironmentVariable("SMTP_PASSWORD"); - - _options = new Options() - { - UserName = USERNAME, - Password = string.IsNullOrWhiteSpace(passwordFromEnvironment) ? PASSWORD : passwordFromEnvironment, - SMTPServer = SMTPADDRESS, - Port = PORT, - UseSsl = USESSL, - UseWindowsAuthentication = USEWINDOWSAUTHENTICATION, - }; + _localAttachmentFolder = Path.Combine(Path.GetTempPath(), TEMP_ATTACHMENT_SOURCE); - } - [TearDown] - public void EmailTestTearDown() + if (!Directory.Exists(_localAttachmentFolder)) + Directory.CreateDirectory(_localAttachmentFolder); + + _filepath = Path.Combine(_localAttachmentFolder, TEST_FILE_NAME); + + if (!File.Exists(_filepath)) { - if (Directory.Exists(_localAttachmentFolder)) - Directory.Delete(_localAttachmentFolder, true); + File.Create(_filepath).Dispose(); } - [Test] - public void SendEmailWithPlainText() + _input = new Input() { - var input = _input; - input.Subject = "Email test - PlainText"; + From = FROMEMAILADDRESS, + To = TOEMAILADDRESS, + Cc = "", + Bcc = "", + Message = "testmsg", + IsMessageHtml = false, + SenderName = "EmailTestSender", + MessageEncoding = "utf-8" + }; + + _input2 = new Input() + { + From = FROMEMAILADDRESS, + To = TOEMAILADDRESS, + Cc = null, + Bcc = null, + Message = "testmsg", + IsMessageHtml = false, + SenderName = "EmailTestSender", + MessageEncoding = "utf-8" + }; + + _options = new Options() + { + UserName = USERNAME, + Password = PASSWORD, + SMTPServer = SMTPADDRESS, + Port = PORT, + UseSsl = USESSL, + UseWindowsAuthentication = USEWINDOWSAUTHENTICATION, + }; - var result = SMTP.SendEmail(input, null, _options, new System.Threading.CancellationToken()); - Assert.IsTrue(result.EmailSent); - } + } + [TearDown] + public void EmailTestTearDown() + { + if (Directory.Exists(_localAttachmentFolder)) + Directory.Delete(_localAttachmentFolder, true); + } - [Test] - public void SendEmailWithFileAttachment() - { - var input = _input; - input.Subject = "Email test - FileAttachment"; + [Test] + public void SendEmailWithPlainText() + { + var input = _input; + input.Subject = "Email test - PlainText"; - var attachment = new Attachment - { - FilePath = _filepath, - SendIfNoAttachmentsFound = false, - ThrowExceptionIfAttachmentNotFound = true - }; + var result = SMTP.SendEmail(input, null, _options, default); + Assert.IsTrue(result.EmailSent); + } + [Test] + public void SendEmailWithFileAttachment() + { + var input = _input; + input.Subject = "Email test - FileAttachment"; - var Attachments = new Attachment[] { attachment }; + var attachment = new Attachment + { + AttachmentType = AttachmentType.FileAttachment, + FilePath = _filepath, + SendIfNoAttachmentsFound = false, + ThrowExceptionIfAttachmentNotFound = true + }; - var result = SMTP.SendEmail(input, Attachments, _options, new System.Threading.CancellationToken()); - Assert.IsTrue(result.EmailSent); - } - [Test] - public void SendEmailWithStringAttachment() + var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } }; + + var result = SMTP.SendEmail(input, Attachments, _options, default); + Assert.IsTrue(result.EmailSent); + } + + [Test] + public void SendEmailWithStringAttachment() + { + var input = _input; + input.Subject = "Email test - AttachmentFromString"; + var fileAttachment = new AttachmentFromString() { FileContent = "teststring � �", FileName = "testfilefromstring.txt" }; + var attachment = new Attachment() { - var input = _input; - input.Subject = "Email test - AttachmentFromString"; - var fileAttachment = new AttachmentFromString() { FileContent = "teststring � �", FileName = "testfilefromstring.txt" }; - var attachment = new Attachment() - { - AttachmentType = AttachmentType.AttachmentFromString, - stringAttachment = fileAttachment - }; - var Attachments = new Attachment[] { attachment }; - - var result = SMTP.SendEmail(input, Attachments, _options, new System.Threading.CancellationToken()); - Assert.IsTrue(result.EmailSent); - } + AttachmentType = AttachmentType.AttachmentFromString, + StringAttachment = fileAttachment + }; + var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } }; + + var result = SMTP.SendEmail(input, Attachments, _options, default); + Assert.IsTrue(result.EmailSent); + } + + [Test] + public void TrySendingEmailWithNoFileAttachmentFound() + { + var input = _input; + input.Subject = "Email test"; - [Test] - public void TrySendingEmailWithNoFileAttachmentFound() + var attachment = new Attachment { - var input = _input; - input.Subject = "Email test"; + FilePath = Path.Combine(_localAttachmentFolder, TEST_FILE_NOT_EXISTING), + SendIfNoAttachmentsFound = false, + ThrowExceptionIfAttachmentNotFound = false + }; - var attachment = new Attachment - { - FilePath = Path.Combine(_localAttachmentFolder, TEST_FILE_NOT_EXISTING), - SendIfNoAttachmentsFound = false, - ThrowExceptionIfAttachmentNotFound = false - }; + var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } }; - var Attachments = new Attachment[] { attachment }; + var result = SMTP.SendEmail(input, Attachments, _options, default); + Assert.IsFalse(result.EmailSent); + } - var result = SMTP.SendEmail(input, Attachments, _options, new System.Threading.CancellationToken()); - Assert.IsFalse(result.EmailSent); - } + [Test] + public void TrySendingEmailWithNoCcAndBcc() + { + var input = _input2; + input.Subject = "Email test"; - [Test] - public void TrySendingEmailWithNoCcAndBcc() + var attachment = new Attachment { - var input = _input2; - input.Subject = "Email test"; + FilePath = Path.Combine(_localAttachmentFolder, TEST_FILE_NOT_EXISTING), + SendIfNoAttachmentsFound = false, + ThrowExceptionIfAttachmentNotFound = false + }; - var attachment = new Attachment - { - FilePath = Path.Combine(_localAttachmentFolder, TEST_FILE_NOT_EXISTING), - SendIfNoAttachmentsFound = false, - ThrowExceptionIfAttachmentNotFound = false - }; + var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } }; - var Attachments = new Attachment[] { attachment }; + var result = SMTP.SendEmail(input, Attachments, _options, default); + Assert.IsFalse(result.EmailSent); + } - var result = SMTP.SendEmail(input, Attachments, _options, new System.Threading.CancellationToken()); - Assert.IsFalse(result.EmailSent); - } + [Test] + public void TrySendingEmailWithNoFileAttachmentFoundException() + { + var input = _input; + input.Subject = "Email test"; - [Test] - public void TrySendingEmailWithNoFileAttachmentFoundException() + var attachment = new Attachment { - var input = _input; - input.Subject = "Email test"; + FilePath = Path.Combine(_localAttachmentFolder, TEST_FILE_NOT_EXISTING), + SendIfNoAttachmentsFound = false, + ThrowExceptionIfAttachmentNotFound = true + }; - var attachment = new Attachment - { - FilePath = Path.Combine(_localAttachmentFolder, TEST_FILE_NOT_EXISTING), - SendIfNoAttachmentsFound = false, - ThrowExceptionIfAttachmentNotFound = true - }; + var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } }; - var Attachments = new Attachment[] { attachment }; + Assert.Throws(() => SMTP.SendEmail(input, Attachments, _options, default)); - Assert.Throws(() => SMTP.SendEmail(input, Attachments, _options, new System.Threading.CancellationToken())); - - } } } diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.sln b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.sln index f08290e..3e11d13 100644 --- a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.sln +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.sln @@ -1,60 +1,60 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32014.148 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frends.SMTP.SendEmail", "Frends.Smtp.SendEmail\Frends.SMTP.SendEmail.csproj", "{F2AD332F-A8DC-42A3-9164-EA58B66E25A5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frends.SMTP.Tests", "Frends.Smtp.SendEmail.Tests\Frends.SMTP.Tests.csproj", "{2E78DC58-381F-48E1-8C9E-734C585AF4C3}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{90CC0DB4-C4A4-4AE3-9705-86A37CE04496}" - ProjectSection(SolutionItems) = preProject - CHANGELOG.md = CHANGELOG.md - README.md = README.md - ..\.github\workflows\SendEmail_dev.yml = ..\.github\workflows\SendEmail_dev.yml - ..\.github\workflows\SendEmail_main.yml = ..\.github\workflows\SendEmail_main.yml - ..\.github\workflows\SendEmail_release.yml = ..\.github\workflows\SendEmail_release.yml - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|x64.ActiveCfg = Debug|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|x64.Build.0 = Debug|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|x86.ActiveCfg = Debug|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|x86.Build.0 = Debug|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|Any CPU.Build.0 = Release|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|x64.ActiveCfg = Release|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|x64.Build.0 = Release|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|x86.ActiveCfg = Release|Any CPU - {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|x86.Build.0 = Release|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|x64.ActiveCfg = Debug|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|x64.Build.0 = Debug|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|x86.ActiveCfg = Debug|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|x86.Build.0 = Debug|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|Any CPU.Build.0 = Release|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|x64.ActiveCfg = Release|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|x64.Build.0 = Release|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|x86.ActiveCfg = Release|Any CPU - {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CABF04CB-0984-4A7A-89C5-2C2BA7285850} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frends.SMTP.SendEmail", "Frends.Smtp.SendEmail\Frends.SMTP.SendEmail.csproj", "{F2AD332F-A8DC-42A3-9164-EA58B66E25A5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frends.SMTP.Tests", "Frends.Smtp.SendEmail.Tests\Frends.SMTP.Tests.csproj", "{2E78DC58-381F-48E1-8C9E-734C585AF4C3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{90CC0DB4-C4A4-4AE3-9705-86A37CE04496}" + ProjectSection(SolutionItems) = preProject + CHANGELOG.md = CHANGELOG.md + README.md = README.md + ..\.github\workflows\SendEmail_build_and_test_on_main.yml = ..\.github\workflows\SendEmail_build_and_test_on_main.yml + ..\.github\workflows\SendEmail_build_and_test_on_push.yml = ..\.github\workflows\SendEmail_build_and_test_on_push.yml + ..\.github\workflows\SendEmail_release.yml = ..\.github\workflows\SendEmail_release.yml + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|x64.ActiveCfg = Debug|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|x64.Build.0 = Debug|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|x86.ActiveCfg = Debug|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Debug|x86.Build.0 = Debug|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|Any CPU.Build.0 = Release|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|x64.ActiveCfg = Release|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|x64.Build.0 = Release|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|x86.ActiveCfg = Release|Any CPU + {F2AD332F-A8DC-42A3-9164-EA58B66E25A5}.Release|x86.Build.0 = Release|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|x64.ActiveCfg = Debug|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|x64.Build.0 = Debug|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|x86.ActiveCfg = Debug|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Debug|x86.Build.0 = Debug|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|Any CPU.Build.0 = Release|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|x64.ActiveCfg = Release|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|x64.Build.0 = Release|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|x86.ActiveCfg = Release|Any CPU + {2E78DC58-381F-48E1-8C9E-734C585AF4C3}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CABF04CB-0984-4A7A-89C5-2C2BA7285850} + EndGlobalSection +EndGlobal diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions.cs deleted file mode 100644 index 5ac23e0..0000000 --- a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions.cs +++ /dev/null @@ -1,200 +0,0 @@ -using System.ComponentModel; -using System.ComponentModel.DataAnnotations; - -namespace Frends.SMTP.SendEmail -{ - public class Input - { - /// - /// Recipient addresses separated by ',' or ';' - /// - /// jane.doe@example.org - [DefaultValue("\"jane.doe@example.org\"")] - public string To { get; set; } - - /// - /// Cc recipient addresses separated by ',' or ';' - /// - /// jane.doe@example.org - [DefaultValue("\"jane.doe@example.org\"")] - public string Cc { get; set; } - - /// - /// Bcc recipient addresses separated by ',' or ';' - /// - /// jane.doe@example.org - [DefaultValue("\"jane.doe@example.org\"")] - public string Bcc { get; set; } - - /// - /// Sender address. - /// - /// john.doe@example.org - [DefaultValue("\"john.doe@example.org\"")] - public string From { get; set; } - - /// - /// Name of the sender. - /// - /// Frends - [DefaultValue("\"\"")] - public string SenderName { get; set; } - - /// - /// Email message's subject. - /// - /// Hello Jane - [DefaultValue("\"Hello Jane\"")] - public string Subject { get; set; } - - /// - /// Body of the message. - /// - /// You've got mail! - [DefaultValue("\"You've got mail!\"")] - public string Message { get; set; } - - /// - /// Set this true if the message is HTML. - /// - /// true - [DefaultValue("false")] - public bool IsMessageHtml { get; set; } - - /// - /// Encoding of message body and subject. Use following table's name column for other options. https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx#Anchor_5 - /// - /// utf-8 - [DefaultValue("\"utf-8\"")] - public string MessageEncoding { get; set; } - - } - - public class Options - { - /// - /// SMTP server address. - /// - /// smtp.somedomain.com - [DefaultValue("\"smtp.somedomain.com\"")] - public string SMTPServer { get; set; } - - /// - /// SMTP server port. - /// - /// 25 - [DefaultValue("25")] - public int Port { get; set; } - - /// - /// Set this true if SMTP expects to be connected using SSL. - /// - /// true - [DefaultValue("false")] - public bool UseSsl { get; set; } - - /// - /// Set this true if you want to use windows authentication to authenticate to SMTP server. - /// - /// true - [DefaultValue("true")] - public bool UseWindowsAuthentication { get; set; } - - /// - /// Use this username to log in to the SMTP server - /// - /// username - [DefaultValue("\"\"")] - [UIHint(nameof(UseWindowsAuthentication), "", false)] - public string UserName { get; set; } - - /// - /// Use this password to log in to the SMTP server - /// - /// Password123 - [PasswordPropertyText(true)] - [DefaultValue("\"\"")] - [UIHint(nameof(UseWindowsAuthentication), "", false)] - public string Password { get; set; } - } - - public class Output - { - /// - /// Value is true if email was sent. - /// - /// true - public bool EmailSent { get; set; } - /// - /// Contains information about the task's result. - /// - /// No attachments found matching path \"C:\\temp\\*.csv\". No email sent. - public string StatusString { get; set; } - } - - public class Attachment - { - /// - /// Chooses if the attachment file is created from a string or copied from disk. - /// - /// FileAttachment - public AttachmentType AttachmentType { get; set; } - - [UIHint(nameof(AttachmentType), "", AttachmentType.AttachmentFromString)] - public AttachmentFromString stringAttachment { get; set; } - - /// - /// Attachment file's path. Uses Directory.GetFiles(string, string) as a pattern matching technique. See https://msdn.microsoft.com/en-us/library/wz42302f(v=vs.110).aspx. - /// Exception: If the path ends in a directory, all files in that folder are added as attachments. - /// - /// /my/attachment/dir - [DefaultValue("\"\"")] - [UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)] - public string FilePath { get; set; } - - /// - /// If set true and no files match the given path, an exception is thrown. - /// - /// true - [UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)] - public bool ThrowExceptionIfAttachmentNotFound { get; set; } - - /// - /// If set true and no files match the given path, email will be sent nevertheless. - /// - /// true - [UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)] - public bool SendIfNoAttachmentsFound { get; set; } - } - public enum AttachmentType - { - /// - /// Select this if the attachment is a file. - /// - FileAttachment, - - /// - /// Select this if the attachment file should be created from a string. - /// - AttachmentFromString - } - - public class AttachmentFromString - { - /// - /// Content of the attachment file - /// - /// My attachment content - [DefaultValue("\"\"")] - [DisplayFormat(DataFormatString = "Text")] - public string FileContent { get; set; } - - /// - /// Name of the attachment file - /// - /// MyAttachment.txt - [DefaultValue("\"\"")] - [DisplayFormat(DataFormatString = "Text")] - public string FileName { get; set; } - } -} diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Attachment.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Attachment.cs new file mode 100644 index 0000000..8133139 --- /dev/null +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Attachment.cs @@ -0,0 +1,42 @@ +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; + +namespace Frends.SMTP.SendEmail.Definitions; + +/// +/// Attachment +/// +public class Attachment +{ + /// + /// Chooses if the attachment file is created from a string or copied from disk. + /// + public AttachmentType AttachmentType { get; set; } + + /// + /// Attachment from string. + /// + [UIHint(nameof(AttachmentType), "", AttachmentType.AttachmentFromString)] + public AttachmentFromString StringAttachment { get; set; } + + /// + /// Attachment file's path. Uses Directory.GetFiles(string, string) as a pattern matching technique. See https://msdn.microsoft.com/en-us/library/wz42302f(v=vs.110).aspx. + /// Exception: If the path ends in a directory, all files in that folder are added as attachments. + /// + [DefaultValue("")] + [UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)] + public string FilePath { get; set; } + + /// + /// If set true and no files match the given path, an exception is thrown. + /// + [UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)] + public bool ThrowExceptionIfAttachmentNotFound { get; set; } + + /// + /// If set true and no files match the given path, email will be sent nevertheless. + /// + [UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)] + public bool SendIfNoAttachmentsFound { get; set; } +} + diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentFromString.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentFromString.cs new file mode 100644 index 0000000..bae919a --- /dev/null +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentFromString.cs @@ -0,0 +1,22 @@ +using System.ComponentModel; + +namespace Frends.SMTP.SendEmail.Definitions; + +/// +/// Parameters for adding attachment from string. +/// +public class AttachmentFromString +{ + /// + /// Content of the attachment file + /// + [DefaultValue("")] + public string FileContent { get; set; } + + /// + /// Name of the attachment file + /// + [DefaultValue("")] + public string FileName { get; set; } +} + diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentOptions.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentOptions.cs new file mode 100644 index 0000000..882e68b --- /dev/null +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentOptions.cs @@ -0,0 +1,16 @@ +namespace Frends.SMTP.SendEmail.Definitions; + +/// +/// Parameters for attachments. +/// +public class AttachmentOptions +{ + /// + /// Array of Attachments to be send with the message. + /// + /// [ + /// Attachment { AttachmentType = AttachmentType.FileAttachment, FilePath = C:\pathToTheFile\test.txt, SendIfNoAttachmentsFound = false, ThrowExceptionIfAttachmentNotFound = true }, + /// Attachment { AttachmentType = AttachmentType.AttachmentFromString, AttachmentFromString { FileContent = This is test file, FileName = testfile.txt } } ] + public Attachment[] Attachments { get; set; } +} + diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentType.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentType.cs new file mode 100644 index 0000000..314e4f8 --- /dev/null +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/AttachmentType.cs @@ -0,0 +1,18 @@ +namespace Frends.SMTP.SendEmail.Definitions; + +/// +/// Enumeration for Attachment type. +/// +public enum AttachmentType +{ + /// + /// Select this if the attachment is a file. + /// + FileAttachment, + + /// + /// Select this if the attachment file should be created from a string. + /// + AttachmentFromString +} + diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Input.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Input.cs new file mode 100644 index 0000000..21cce39 --- /dev/null +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Input.cs @@ -0,0 +1,74 @@ +using System.ComponentModel; + +namespace Frends.SMTP.SendEmail.Definitions; + +/// +/// Input parameters. +/// +public class Input +{ + /// + /// Recipient addresses separated by ',' or ';' + /// + /// jane.doe@somedomain.com + [DefaultValue("jane.doe@somedomain.com")] + public string To { get; set; } + + /// + /// Cc recipient addresses separated by ',' or ';' + /// + /// jane.doe@somedomain.com + [DefaultValue("jane.doe@somedomain.com")] + public string Cc { get; set; } + + /// + /// Bcc recipient addresses separated by ',' or ';' + /// + /// jane.doe@somedomain.com + [DefaultValue("jane.doe@somedomain.com")] + public string Bcc { get; set; } + + /// + /// Sender address. + /// + /// jane.doe@somedomain.com + [DefaultValue("john.doe@somedomain.com")] + public string From { get; set; } + + /// + /// Name of the sender. + /// + /// Jane Doe + [DefaultValue("")] + public string SenderName { get; set; } + + /// + /// Email message's subject. + /// + /// Hello Jane + [DefaultValue("Hello Jane")] + public string Subject { get; set; } + + /// + /// Body of the message. + /// + /// You've got mail! + [DefaultValue("You've got mail!")] + public string Message { get; set; } + + /// + /// Set this true if the message is HTML. + /// + /// true + [DefaultValue("false")] + public bool IsMessageHtml { get; set; } + + /// + /// Encoding of message body and subject. Use following table's name column for other options. https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx#Anchor_5 + /// + /// utf-8 + [DefaultValue("utf-8")] + public string MessageEncoding { get; set; } + +} + diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Options.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Options.cs new file mode 100644 index 0000000..aae9903 --- /dev/null +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Options.cs @@ -0,0 +1,55 @@ +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; + +namespace Frends.SMTP.SendEmail.Definitions; + +/// +/// SMTP Options parameters. +/// +public class Options +{ + /// + /// SMTP server address. + /// + /// smtp.somedomain.com + [DefaultValue("smtp.somedomain.com")] + public string SMTPServer { get; set; } + + /// + /// SMTP server port. + /// + /// 25 + [DefaultValue("25")] + public int Port { get; set; } + + /// + /// Set this true if SMTP expects to be connected using SSL. + /// + /// true + [DefaultValue("false")] + public bool UseSsl { get; set; } + + /// + /// Set this true if you want to use windows authentication to authenticate to SMTP server. + /// + /// false + [DefaultValue("true")] + public bool UseWindowsAuthentication { get; set; } + + /// + /// Use this username to log in to the SMTP server + /// + /// testuser + [DefaultValue("")] + [UIHint(nameof(UseWindowsAuthentication), "", false)] + public string UserName { get; set; } + + /// + /// Use this password to log in to the SMTP server + /// + /// Password123 + [PasswordPropertyText(true)] + [DefaultValue("")] + [UIHint(nameof(UseWindowsAuthentication), "", false)] + public string Password { get; set; } +} diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Result.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Result.cs new file mode 100644 index 0000000..799ed7a --- /dev/null +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Result.cs @@ -0,0 +1,26 @@ +namespace Frends.SMTP.SendEmail.Definitions; + +/// +/// Result class of the Task. +/// +public class Result +{ + internal Result(bool emailSent, string status) + { + EmailSent = emailSent; + StatusString = status; + } + + /// + /// Value is true if email was sent. + /// + /// true + public bool EmailSent { get; private set; } + + /// + /// Contains information about the task's result. + /// + /// Email sent to: john.doe@somedomain.com + public string StatusString { get; private set; } +} + diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Frends.Smtp.SendEmail.csproj b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Frends.Smtp.SendEmail.csproj index 1ccad62..1572356 100644 --- a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Frends.Smtp.SendEmail.csproj +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Frends.Smtp.SendEmail.csproj @@ -1,9 +1,10 @@ - + - netstandard2.0;net6.0 - 1.0.3 + net6.0 + 1.1.0 + latest Frends Frends Frends diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/GlobalSuppressions.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/GlobalSuppressions.cs new file mode 100644 index 0000000..586b721 --- /dev/null +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/GlobalSuppressions.cs @@ -0,0 +1,4 @@ +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "Following Frends guidelines", Scope = "type", Target = "~T:Frends.SMTP.SendEmail.SMTP")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File should have header", Justification = "Following Frends guidelines")] diff --git a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/SendEmailTask.cs b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/SendEmailTask.cs index 9b1c5b4..a05ca87 100644 --- a/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/SendEmailTask.cs +++ b/Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/SendEmailTask.cs @@ -1,158 +1,148 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Net; -using System.Net.Mail; -using System.Text; -using System.Threading; -namespace Frends.SMTP.SendEmail -{ -#pragma warning disable S101 // Types should be named in PascalCase - public static class SMTP -#pragma warning restore S101 // Types should be named in PascalCase - - { - /// - /// Sends email message with optional attachments. - /// [Documentation](https://github.com/FrendsPlatform/Frends.SMTP/tree/main/Frends.SMTP.SendEmail) - /// - /// - /// Object { bool EmailSent, string StatusString } - /// - public static Output SendEmail([PropertyTab] Input message, [PropertyTab] Attachment[] attachments, [PropertyTab] Options SMTPSettings, CancellationToken cancellationToken) - { - var output = new Output(); - - using (var client = InitializeSmtpClient(SMTPSettings)) - { - using (var mail = InitializeMailMessage(message)) - { - if (attachments != null) - foreach (var attachment in attachments) - { - if (attachment.AttachmentType == AttachmentType.FileAttachment) - { - ICollection allAttachmentFilePaths = GetAttachmentFiles(attachment.FilePath); - - if (attachment.ThrowExceptionIfAttachmentNotFound && allAttachmentFilePaths.Count == 0) - throw new FileNotFoundException(string.Format("The given filepath \"{0}\" had no matching files", attachment.FilePath), attachment.FilePath); - - if (allAttachmentFilePaths.Count == 0 && !attachment.SendIfNoAttachmentsFound) - { - output.StatusString = string.Format("No attachments found matching path \"{0}\". No email sent.", attachment.FilePath); - output.EmailSent = false; - return output; - } - - foreach (var fp in allAttachmentFilePaths) - { - mail.Attachments.Add(new System.Net.Mail.Attachment(fp)); - } - } - - if (attachment.AttachmentType == AttachmentType.AttachmentFromString - && !string.IsNullOrEmpty(attachment.stringAttachment.FileContent)) - { - mail.Attachments.Add(System.Net.Mail.Attachment.CreateAttachmentFromString - (attachment.stringAttachment.FileContent, attachment.stringAttachment.FileName)); - } - - } - - cancellationToken.ThrowIfCancellationRequested(); - - client.Send(mail); - - output.EmailSent = true; - output.StatusString = string.Format("Email sent to: {0}", mail.To.ToString()); - - return output; - } - } - } - - /// - /// Initializes new SmtpClient with given parameters. - /// - private static SmtpClient InitializeSmtpClient(Options settings) - { - var smtpClient = new SmtpClient - { - Port = settings.Port, - DeliveryMethod = SmtpDeliveryMethod.Network, - UseDefaultCredentials = settings.UseWindowsAuthentication, - EnableSsl = settings.UseSsl, - Host = settings.SMTPServer - }; - - if (!settings.UseWindowsAuthentication && !string.IsNullOrEmpty(settings.UserName)) - smtpClient.Credentials = new NetworkCredential(settings.UserName, settings.Password); - - return smtpClient; - } - - /// - /// Initializes new MailMessage with given parameters. Uses default value 'true' for IsBodyHtml - /// - private static MailMessage InitializeMailMessage(Input input) - { - //split recipients, either by comma or semicolon - var separators = new[] { ',', ';' }; - - string[] recipients = string.IsNullOrEmpty(input.To) - ? new string[] { } - : input.To.Split(separators, StringSplitOptions.RemoveEmptyEntries); - string[] ccRecipients = string.IsNullOrEmpty(input.Cc) - ? new string[] { } - : input.Cc.Split(separators, StringSplitOptions.RemoveEmptyEntries); - string[] bccRecipients = string.IsNullOrEmpty(input.Bcc) - ? new string[] { } - : input.Bcc.Split(separators, StringSplitOptions.RemoveEmptyEntries); - - //Create mail object - var mail = new MailMessage() - { - From = new MailAddress(input.From, input.SenderName), - Subject = input.Subject, - Body = input.Message, - IsBodyHtml = input.IsMessageHtml - }; - //Add recipients - foreach (var recipientAddress in recipients) - { - mail.To.Add(recipientAddress); - } - //Add CC recipients - foreach (var ccRecipient in ccRecipients) - { - mail.CC.Add(ccRecipient); - } - //Add BCC recipients - foreach (var bccRecipient in bccRecipients) - { - mail.Bcc.Add(bccRecipient); - } - //Set message encoding - Encoding encoding = Encoding.GetEncoding(input.MessageEncoding); - - mail.BodyEncoding = encoding; - mail.SubjectEncoding = encoding; - - return mail; - } - - /// - /// Gets all actual file names of attachments matching given file path - /// - private static ICollection GetAttachmentFiles(string filePath) - { - string folder = Path.GetDirectoryName(filePath); - string fileMask = Path.GetFileName(filePath) != "" ? Path.GetFileName(filePath) : "*"; - - string[] filePaths = Directory.GetFiles(folder, fileMask); - - return filePaths; - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Net; +using System.Net.Mail; +using System.Text; +using System.Threading; +using Frends.SMTP.SendEmail.Definitions; + +namespace Frends.SMTP.SendEmail; +/// +/// Main class of the Task. +/// +public static class SMTP +{ + /// + /// Sends email message with optional attachments. + /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.SMTP.SendEmail) + /// + /// Message parameters. + /// Parameters for adding attachments. + /// Connection parameters. + /// Token given by Frends to terminate the Task. + /// Object { bool EmailSent, string StatusString } + public static Result SendEmail([PropertyTab] Input message, [PropertyTab] AttachmentOptions attachments, [PropertyTab] Options SMTPSettings, CancellationToken cancellationToken) + { + using var client = InitializeSmtpClient(SMTPSettings); + using var mail = InitializeMailMessage(message, cancellationToken); + if (attachments != null) + foreach (var attachment in attachments.Attachments) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (attachment.AttachmentType == AttachmentType.FileAttachment) + { + ICollection allAttachmentFilePaths = GetAttachmentFiles(attachment.FilePath); + + if (attachment.ThrowExceptionIfAttachmentNotFound && allAttachmentFilePaths.Count == 0) + throw new FileNotFoundException($@"The given filepath ""attachment.FilePath"" had no matching files", attachment.FilePath); + + if (allAttachmentFilePaths.Count == 0 && !attachment.SendIfNoAttachmentsFound) + return new Result(false, $@"No attachments found matching path ""{attachment.FilePath}"". No email sent."); + + foreach (var fp in allAttachmentFilePaths) + { + cancellationToken.ThrowIfCancellationRequested(); + mail.Attachments.Add(new System.Net.Mail.Attachment(fp)); + } + } + + if (attachment.AttachmentType == AttachmentType.AttachmentFromString + && !string.IsNullOrEmpty(attachment.StringAttachment.FileContent)) + mail.Attachments.Add(System.Net.Mail.Attachment.CreateAttachmentFromString + (attachment.StringAttachment.FileContent, attachment.StringAttachment.FileName)); + } + + client.Send(mail); + + return new Result(true, $"Email sent to: {mail.To}"); + } + + /// + /// Initializes new SmtpClient with given parameters. + /// + private static SmtpClient InitializeSmtpClient(Options settings) + { + var smtpClient = new SmtpClient + { + Port = settings.Port, + DeliveryMethod = SmtpDeliveryMethod.Network, + UseDefaultCredentials = settings.UseWindowsAuthentication, + EnableSsl = settings.UseSsl, + Host = settings.SMTPServer + }; + + if (!settings.UseWindowsAuthentication && !string.IsNullOrEmpty(settings.UserName)) + smtpClient.Credentials = new NetworkCredential(settings.UserName, settings.Password); + + return smtpClient; + } + + /// + /// Initializes new MailMessage with given parameters. Uses default value 'true' for IsBodyHtml + /// + private static MailMessage InitializeMailMessage(Input input, CancellationToken cancellationToken) + { + //split recipients, either by comma or semicolon + var separators = new[] { ',', ';' }; + + string[] recipients = string.IsNullOrEmpty(input.To) + ? Array.Empty() + : input.To.Split(separators, StringSplitOptions.RemoveEmptyEntries); + string[] ccRecipients = string.IsNullOrEmpty(input.Cc) + ? Array.Empty() + : input.Cc.Split(separators, StringSplitOptions.RemoveEmptyEntries); + string[] bccRecipients = string.IsNullOrEmpty(input.Bcc) + ? Array.Empty() + : input.Bcc.Split(separators, StringSplitOptions.RemoveEmptyEntries); + + //Create mail object + var mail = new MailMessage() + { + From = new MailAddress(input.From, input.SenderName), + Subject = input.Subject, + Body = input.Message, + IsBodyHtml = input.IsMessageHtml + }; + //Add recipients + foreach (var recipientAddress in recipients) + { + cancellationToken.ThrowIfCancellationRequested(); + mail.To.Add(recipientAddress); + } + //Add CC recipients + foreach (var ccRecipient in ccRecipients) + { + cancellationToken.ThrowIfCancellationRequested(); + mail.CC.Add(ccRecipient); + } + //Add BCC recipients + foreach (var bccRecipient in bccRecipients) + { + cancellationToken.ThrowIfCancellationRequested(); + mail.Bcc.Add(bccRecipient); + } + //Set message encoding + Encoding encoding = Encoding.GetEncoding(input.MessageEncoding); + + mail.BodyEncoding = encoding; + mail.SubjectEncoding = encoding; + + return mail; + } + + /// + /// Gets all actual file names of attachments matching given file path + /// + private static ICollection GetAttachmentFiles(string filePath) + { + string folder = Path.GetDirectoryName(filePath); + string fileMask = Path.GetFileName(filePath) != "" ? Path.GetFileName(filePath) : "*"; + + string[] filePaths = Directory.GetFiles(folder, fileMask); + + return filePaths; + } +} diff --git a/Frends.SMTP.SendEmail/README.md b/Frends.SMTP.SendEmail/README.md index 6d8de4e..6f1ffff 100644 --- a/Frends.SMTP.SendEmail/README.md +++ b/Frends.SMTP.SendEmail/README.md @@ -1,11 +1,10 @@ # Frends.SMTP.SendEmail +Frends task for sending emails with SMTP. Task sends emails via SMTP protocol and can handle attachments either from file or as raw string input. -[![Frends.Smtp.SendEmail Main](https://github.com/FrendsPlatform/Frends.Smtp/actions/workflows/SendEmail_main.yml/badge.svg)](https://github.com/FrendsPlatform/Frends.Regex/actions/workflows/IsMatch_build_and_test_on_main.yml) - ![GitHub](https://img.shields.io/github/license/FrendsPlatform/Frends.Smtp?label=License) - ![Coverage](https://app-github-custom-badges.azurewebsites.net/Badge?key=FrendsPlatform/Frends.Smtp/Frends.Smtp.SendEmail|main) - -Frends task for sending emails with SMTP. Task sends emails via SMTP protocol and can handle attachments either from file or as raw string input. +[![Frends.Smtp.SendEmail Main](https://github.com/FrendsPlatform/Frends.SMTP/actions/workflows/SendEmail_build_and_test_on_main.yml/badge.svg)](https://github.com/FrendsPlatform/Frends.SMTP/actions) +![GitHub](https://img.shields.io/github/license/FrendsPlatform/Frends.SMTP?label=License) +![Coverage](https://app-github-custom-badges.azurewebsites.net/Badge?key=FrendsPlatform/Frends.SMTP/Frends.SMTP.SendEmail|main) ## Installing @@ -13,14 +12,18 @@ You can install the Task via frends UI Task View. ## Building -Rebuild the project +### Clone a copy of the repository + +`git clone https://github.com/FrendsPlatform/Frends.SMTP.git` + +### Rebuild the project `dotnet build` -Run tests +### Run tests `dotnet test` -Create a NuGet package +### Create a NuGet package `dotnet pack --configuration Release` diff --git a/README.md b/README.md index 8fe4103..8f0159b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Frends tasks for SMTP protocol. # Tasks -- [Frends.Smtp.SendEmail](Frends.Smtp.SendEmail/README.md) +- [Frends.SMTP.SendEmail](Frends.SMTP.SendEmail/README.md) # Contributing When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.