diff --git a/src/NetCore.Utilities.Email.Smtp.Tests/NetCore.Utilities.Email.Smtp.Tests.csproj b/src/NetCore.Utilities.Email.Smtp.Tests/NetCore.Utilities.Email.Smtp.Tests.csproj index ae4ff05..156ac6f 100644 --- a/src/NetCore.Utilities.Email.Smtp.Tests/NetCore.Utilities.Email.Smtp.Tests.csproj +++ b/src/NetCore.Utilities.Email.Smtp.Tests/NetCore.Utilities.Email.Smtp.Tests.csproj @@ -1,23 +1,23 @@  - net6.0 + net8.0 false ICG.NetCore.Utilities.Email.Smtp.Tests - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - + + + + + + + all runtime; build; native; contentfiles; analyzers diff --git a/src/NetCore.Utilities.Email.Smtp.Tests/SmtpServiceTests.cs b/src/NetCore.Utilities.Email.Smtp.Tests/SmtpServiceTests.cs index 85156b8..d90dd69 100644 --- a/src/NetCore.Utilities.Email.Smtp.Tests/SmtpServiceTests.cs +++ b/src/NetCore.Utilities.Email.Smtp.Tests/SmtpServiceTests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Microsoft.Extensions.Options; using MimeKit; using Moq; @@ -60,7 +61,7 @@ public void AdminEmail_ShouldReturnNullWhenNoConfiguration() } [Fact] - public void SendToAdministrator_ShouldSend_DefaultingFromAndToAddress() + public async Task SendToAdministratorAsync_ShouldSend_DefaultingFromAndToAddress() { //Arrange var subject = "Test"; @@ -71,15 +72,15 @@ public void SendToAdministrator_ShouldSend_DefaultingFromAndToAddress() .Returns(mimeMessage).Verifiable(); //Act - _service.SendMessageToAdministrator(subject, message); + await _service.SendMessageToAdministratorAsync(subject, message); //Verify _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendToAdministrator_ShouldSend_DefaultingFromAndToAddress_WithCCRecipients() + public async Task SendToAdministrator_ShouldSend_DefaultingFromAndToAddress_WithCCRecipients() { //Arrange var subject = "Test"; @@ -91,15 +92,15 @@ public void SendToAdministrator_ShouldSend_DefaultingFromAndToAddress_WithCCReci .Returns(mimeMessage).Verifiable(); //Act - _service.SendMessageToAdministrator(cc, subject, message); + await _service.SendMessageToAdministratorAsync(cc, subject, message); //Verify _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendMessage_WithoutCCRecipients_ShouldSend_DefaultingFromAddress() + public async Task SendMessage_WithoutCCRecipients_ShouldSend_DefaultingFromAddress() { //Arrange var to = "tester@test.com"; @@ -111,15 +112,15 @@ public void SendMessage_WithoutCCRecipients_ShouldSend_DefaultingFromAddress() .Returns(mimeMessage).Verifiable(); //Act - _service.SendMessage(to, subject, message); + await _service.SendMessageAsync(to, subject, message); //Verify _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendMessageWithReplyTo_WithoutCCRecipients_ShouldSend_DefaultingFromAddress() + public async Task SendMessageWithReplyTo_WithoutCCRecipients_ShouldSend_DefaultingFromAddress() { //Arrange var replyTo = "me@me.com"; @@ -133,18 +134,18 @@ public void SendMessageWithReplyTo_WithoutCCRecipients_ShouldSend_DefaultingFrom .Returns(mimeMessage).Verifiable(); //Act - _service.SendWithReplyTo(replyTo, replyToName, to, subject, message); + await _service.SendWithReplyToAsync(replyTo, replyToName, to, subject, message); //Verify - Assert.Equal(1, mimeMessage.ReplyTo.Count); + Assert.Single(mimeMessage.ReplyTo); var replyToAsAdded = mimeMessage.ReplyTo.First(); Assert.Equal("\"Bob\" ", replyToAsAdded.ToString()); _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendMessage_WithCCRecipients_ShouldSend_DefaultingFromAddress() + public async Task SendMessage_WithCCRecipients_ShouldSend_DefaultingFromAddress() { //Arrange var to = "tester@test.com"; @@ -157,15 +158,15 @@ public void SendMessage_WithCCRecipients_ShouldSend_DefaultingFromAddress() .Returns(mimeMessage).Verifiable(); //Act - _service.SendMessage(to, cc, subject, message); + await _service.SendMessageAsync(to, cc, subject, message); //Verify _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendMessageWithReplyTo_WithCCRecipients_ShouldSend_DefaultingFromAddress() + public async Task SendMessageWithReplyTo_WithCCRecipients_ShouldSend_DefaultingFromAddress() { //Arrange var replyTo = "me@me.com"; @@ -180,18 +181,18 @@ public void SendMessageWithReplyTo_WithCCRecipients_ShouldSend_DefaultingFromAdd .Returns(mimeMessage).Verifiable(); //Act - _service.SendWithReplyTo(replyTo, replyToName, to, cc, subject, message); + await _service.SendWithReplyToAsync(replyTo, replyToName, to, cc, subject, message); //Verify - Assert.Equal(1, mimeMessage.ReplyTo.Count); + Assert.Single(mimeMessage.ReplyTo); var replyToAsAdded = mimeMessage.ReplyTo.First(); Assert.Equal("\"Bob\" ", replyToAsAdded.ToString()); _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendMessageWithAttachment_ShouldSend_DefaultingFromAddress() + public async Task SendMessageWithAttachment_ShouldSend_DefaultingFromAddress() { //Arrange var to = "tester@test.com"; @@ -206,15 +207,15 @@ public void SendMessageWithAttachment_ShouldSend_DefaultingFromAddress() .Returns(mimeMessage).Verifiable(); //Act - _service.SendMessageWithAttachment(to, cc, subject, fileContent, fileName, message, null); + await _service.SendMessageWithAttachmentAsync(to, cc, subject, fileContent, fileName, message, null); //Assets _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendMessage_ShouldPassOptionalTemplateName_ToMessageMethods() + public async Task SendMessage_ShouldPassOptionalTemplateName_ToMessageMethods() { //Arrange var to = "tester@test.com"; @@ -228,15 +229,15 @@ public void SendMessage_ShouldPassOptionalTemplateName_ToMessageMethods() .Returns(mimeMessage).Verifiable(); //Act - _service.SendMessage(to, cc, subject, message, null, requestedTemplate); + await _service.SendMessageAsync(to, cc, subject, message, null, requestedTemplate); //Assets _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendMessageWithReplyTo_ShouldPassOptionalTemplateName_ToMessageMethods() + public async Task SendMessageWithReplyTo_ShouldPassOptionalTemplateName_ToMessageMethods() { //Arrange var replyTo = "me@me.com"; @@ -252,18 +253,18 @@ public void SendMessageWithReplyTo_ShouldPassOptionalTemplateName_ToMessageMetho .Returns(mimeMessage).Verifiable(); //Act - _service.SendWithReplyTo(replyTo, replyToName, to, cc, subject, message, null, requestedTemplate); + await _service.SendWithReplyToAsync(replyTo, replyToName, to, cc, subject, message, null, requestedTemplate); //Assets - Assert.Equal(1, mimeMessage.ReplyTo.Count); + Assert.Single(mimeMessage.ReplyTo); var replyToAsAdded = mimeMessage.ReplyTo.First(); Assert.Equal("\"Bob\" ", replyToAsAdded.ToString()); _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } [Fact] - public void SendMessageWithAttachment_ShouldPassOptionalTemplateName_ToMessageMethods() + public async Task SendMessageWithAttachment_ShouldPassOptionalTemplateName_ToMessageMethods() { //Arrange var to = "tester@test.com"; @@ -279,11 +280,11 @@ public void SendMessageWithAttachment_ShouldPassOptionalTemplateName_ToMessageMe .Returns(mimeMessage).Verifiable(); //Act - _service.SendMessageWithAttachment(to, cc, subject, fileContent, fileName, message, null, requestedTemplate); + await _service.SendMessageWithAttachmentAsync(to, cc, subject, fileContent, fileName, message, null, requestedTemplate); //Assets _mimeMessageFactoryMock.Verify(); - _mimeKitServiceMock.Verify(k => k.SendEmail(mimeMessage)); + _mimeKitServiceMock.Verify(k => k.SendEmailAsync(mimeMessage)); } } } diff --git a/src/NetCore.Utilities.Email.Smtp/MimeKitService.cs b/src/NetCore.Utilities.Email.Smtp/MimeKitService.cs index 500d33e..ddbd7b8 100644 --- a/src/NetCore.Utilities.Email.Smtp/MimeKitService.cs +++ b/src/NetCore.Utilities.Email.Smtp/MimeKitService.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; using MailKit.Net.Smtp; using Microsoft.Extensions.Options; using MimeKit; @@ -14,7 +15,7 @@ public interface IMimeKitService /// Sends an email message /// /// The message to send - void SendEmail(MimeMessage toSend); + Task SendEmailAsync(MimeMessage toSend); } /// @@ -38,13 +39,13 @@ public MimeKitService(IOptions configuration) } /// - public void SendEmail(MimeMessage toSend) + public async Task SendEmailAsync(MimeMessage toSend) { using var client = new SmtpClient(); - client.Connect(_configuration.Value.Server, _configuration.Value.Port, _configuration.Value.UseSsl); + await client.ConnectAsync(_configuration.Value.Server, _configuration.Value.Port, _configuration.Value.UseSsl); client.AuthenticationMechanisms.Remove("XOAUTH2"); - client.Authenticate(_configuration.Value.SenderUsername, _configuration.Value.SenderPassword); - client.Send(toSend); + await client.AuthenticateAsync(_configuration.Value.SenderUsername, _configuration.Value.SenderPassword); + await client.SendAsync(toSend); } } } \ No newline at end of file diff --git a/src/NetCore.Utilities.Email.Smtp/NetCore.Utilities.Email.Smtp.csproj b/src/NetCore.Utilities.Email.Smtp/NetCore.Utilities.Email.Smtp.csproj index dfe9677..fa157d2 100644 --- a/src/NetCore.Utilities.Email.Smtp/NetCore.Utilities.Email.Smtp.csproj +++ b/src/NetCore.Utilities.Email.Smtp/NetCore.Utilities.Email.Smtp.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 ICG.NetCore.Utilities.Email.Smtp true true @@ -10,8 +10,8 @@ ICG.NetCore.Utilities.Email.Smtp NetCore Utilities Email SMTP - A library providing an easy to use set of functions rounding the SMTPClient. - Copyright 2021, IowaComputerGurus, Inc. All Rights Reserved + A library providing easy access to sending emails, including templated emails, via SMTP from .NET 8+. + Copyright 2024, IowaComputerGurus, Inc. All Rights Reserved https://github.com/IowaComputerGurus/netcore.utilities.email.smtp aspnetcore;utility;email https://github.com/IowaComputerGurus/netcore.utilities.email.smtp @@ -33,14 +33,14 @@ - - - - - - - - + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/NetCore.Utilities.Email.Smtp/SmtpService.cs b/src/NetCore.Utilities.Email.Smtp/SmtpService.cs index 945770e..ab49014 100644 --- a/src/NetCore.Utilities.Email.Smtp/SmtpService.cs +++ b/src/NetCore.Utilities.Email.Smtp/SmtpService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.Extensions.Options; using MimeKit; @@ -33,45 +34,45 @@ public SmtpService(IOptions serviceOptions, IMimeMessageFact } /// - public bool SendMessageToAdministrator(string subject, string bodyHtml) + public async Task SendMessageToAdministratorAsync(string subject, string bodyHtml) { //Force to address - return SendMessage(_serviceOptions.AdminEmail, null, subject, bodyHtml, null, ""); + return await SendMessageAsync(_serviceOptions.AdminEmail, null, subject, bodyHtml, null, ""); } /// - public bool SendMessageToAdministrator(IEnumerable ccAddressList, string subject, string bodyHtml) + public async Task SendMessageToAdministratorAsync(IEnumerable ccAddressList, string subject, string bodyHtml) { - return SendMessage(_serviceOptions.AdminEmail, ccAddressList, subject, bodyHtml, null, ""); + return await SendMessageAsync(_serviceOptions.AdminEmail, ccAddressList, subject, bodyHtml, null, ""); } /// - public bool SendMessage(string toAddress, string subject, string bodyHtml) + public async Task SendMessageAsync(string toAddress, string subject, string bodyHtml) { //Call full overload - return SendMessage(toAddress, null, subject, bodyHtml, null, ""); + return await SendMessageAsync(toAddress, null, subject, bodyHtml, null, ""); } /// - public bool SendMessage(string toAddress, string subject, string bodyHtml, List> tokens) + public async Task SendMessageAsync(string toAddress, string subject, string bodyHtml, List> tokens) { - return SendMessage(toAddress, null, subject, bodyHtml, null, ""); + return await SendMessageAsync(toAddress, null, subject, bodyHtml, null, ""); } /// - public bool SendMessage(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml) + public async Task SendMessageAsync(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml) { - return SendMessage(toAddress, ccAddressList, subject, bodyHtml, null, ""); + return await SendMessageAsync(toAddress, ccAddressList, subject, bodyHtml, null, ""); } /// - public bool SendMessage(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens) + public async Task SendMessageAsync(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens) { - return SendMessage(toAddress, ccAddressList, subject, bodyHtml, tokens, ""); + return await SendMessageAsync(toAddress, ccAddressList, subject, bodyHtml, tokens, ""); } /// - public bool SendMessage(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, + public async Task SendMessageAsync(string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens, string templateName, string senderKeyName = "") { @@ -87,15 +88,15 @@ public bool SendMessage(string toAddress, IEnumerable ccAddressList, str //Convert to a mime message var toSend = _mimeMessageFactory.CreateFromMessage(_serviceOptions.AdminEmail, _serviceOptions.AdminName, toAddress, ccAddressList, subject, bodyHtml, templateName); - + //Send - _mimeKitService.SendEmail(toSend); + await _mimeKitService.SendEmailAsync(toSend); return true; //Success } /// - public bool SendMessageWithAttachment(string toAddress, IEnumerable ccAddressList, string subject, + public async Task SendMessageWithAttachmentAsync(string toAddress, IEnumerable ccAddressList, string subject, byte[] fileContent, string fileName, string bodyHtml, List> tokens, string templateName = "", string senderKeyName = "") { //TODO: Optimize this @@ -112,41 +113,41 @@ public bool SendMessageWithAttachment(string toAddress, IEnumerable ccAd ccAddressList, subject, fileContent, fileName, bodyHtml, templateName); //Send - _mimeKitService.SendEmail(toSend); + await _mimeKitService.SendEmailAsync(toSend); return true; } /// - public bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, string subject, string bodyHtml) + public async Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, string subject, string bodyHtml) { //Call full overload - return SendWithReplyTo(replyToAddress, replyToName, toAddress, null, subject, bodyHtml); + return await SendWithReplyToAsync(replyToAddress, replyToName, toAddress, null, subject, bodyHtml); } /// - public bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, string subject, string bodyHtml, List> tokens) + public async Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, string subject, string bodyHtml, List> tokens) { //Call full overload - return SendWithReplyTo(replyToAddress, replyToName, toAddress, null, subject, bodyHtml, null, ""); + return await SendWithReplyToAsync(replyToAddress, replyToName, toAddress, null, subject, bodyHtml, null, ""); } /// - public bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml) + public async Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml) { //Call full overload - return SendWithReplyTo(replyToAddress, replyToName, toAddress, ccAddressList, subject, bodyHtml, null, ""); + return await SendWithReplyToAsync(replyToAddress, replyToName, toAddress, ccAddressList, subject, bodyHtml, null, ""); } /// - public bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens) + public async Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens) { //Call full overload - return SendWithReplyTo(replyToAddress, replyToName, toAddress, ccAddressList, subject, bodyHtml, tokens, ""); + return await SendWithReplyToAsync(replyToAddress, replyToName, toAddress, ccAddressList, subject, bodyHtml, tokens, ""); } /// - public bool SendWithReplyTo(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens, string templateName, string senderKeyName = "") + public async Task SendWithReplyToAsync(string replyToAddress, string replyToName, string toAddress, IEnumerable ccAddressList, string subject, string bodyHtml, List> tokens, string templateName, string senderKeyName = "") { if (string.IsNullOrEmpty(replyToAddress)) throw new ArgumentNullException(nameof(replyToAddress)); @@ -173,7 +174,7 @@ public bool SendWithReplyTo(string replyToAddress, string replyToName, string to } //Send - _mimeKitService.SendEmail(toSend); + await _mimeKitService.SendEmailAsync(toSend); return true; } }