Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SMTP.SendEmail - Add OAuth support #22

Merged
merged 4 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Frends.SMTP.SendEmail/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## [1.2.0] - 2023-12-21
### Changed
- Changed Task to use MailKit library instead of deprecated System.Net.Mail.
- Changed the Task to create a temp file from the AttachmentFromString. The temp file will be removed afterwards.

### Added
- Added OAuth2 support.
- New parameters:
- SecureSocket
- UseOAuth2
- Token

### Removed
- Removed UseWindowsAuthentication because it's not supported with the new library.

## [1.1.0] - 2023-11-29
### Fixed
- [Breaking] Fixed issue with the attachments can't be given as expression by adding AttachmentOptions class.
Expand Down
32 changes: 16 additions & 16 deletions Frends.SMTP.SendEmail/Frends.Smtp.SendEmail.Tests/SendEmailTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using NUnit.Framework;
using System;
using System.IO;
using System.Threading.Tasks;
using Frends.SMTP.SendEmail.Definitions;

namespace Frends.SMTP.SendEmail.Tests;
Expand All @@ -15,8 +16,6 @@ public class SendEmailTests
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;
// ************************************************************************************************************


Expand Down Expand Up @@ -75,11 +74,12 @@ public void EmailTestSetup()
Password = PASSWORD,
SMTPServer = SMTPADDRESS,
Port = PORT,
UseSsl = USESSL,
UseWindowsAuthentication = USEWINDOWSAUTHENTICATION,
UseOAuth2 = false,
SecureSocket = SecureSocketOption.None
};

}

[TearDown]
public void EmailTestTearDown()
{
Expand All @@ -88,17 +88,17 @@ public void EmailTestTearDown()
}

[Test]
public void SendEmailWithPlainText()
public async Task SendEmailWithPlainText()
{
var input = _input;
input.Subject = "Email test - PlainText";

var result = SMTP.SendEmail(input, null, _options, default);
var result = await SMTP.SendEmail(input, null, _options, default);
Assert.IsTrue(result.EmailSent);
}

[Test]
public void SendEmailWithFileAttachment()
public async Task SendEmailWithFileAttachment()
{
var input = _input;
input.Subject = "Email test - FileAttachment";
Expand All @@ -114,12 +114,12 @@ public void SendEmailWithFileAttachment()

var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } };

var result = SMTP.SendEmail(input, Attachments, _options, default);
var result = await SMTP.SendEmail(input, Attachments, _options, default);
Assert.IsTrue(result.EmailSent);
}

[Test]
public void SendEmailWithStringAttachment()
public async Task SendEmailWithStringAttachment()
{
var input = _input;
input.Subject = "Email test - AttachmentFromString";
Expand All @@ -131,12 +131,12 @@ public void SendEmailWithStringAttachment()
};
var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } };

var result = SMTP.SendEmail(input, Attachments, _options, default);
var result = await SMTP.SendEmail(input, Attachments, _options, default);
Assert.IsTrue(result.EmailSent);
}

[Test]
public void TrySendingEmailWithNoFileAttachmentFound()
public async Task TrySendingEmailWithNoFileAttachmentFound()
{
var input = _input;
input.Subject = "Email test";
Expand All @@ -151,12 +151,12 @@ public void TrySendingEmailWithNoFileAttachmentFound()

var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } };

var result = SMTP.SendEmail(input, Attachments, _options, default);
var result = await SMTP.SendEmail(input, Attachments, _options, default);
Assert.IsFalse(result.EmailSent);
}

[Test]
public void TrySendingEmailWithNoCcAndBcc()
public async Task TrySendingEmailWithNoCcAndBcc()
{
var input = _input2;
input.Subject = "Email test";
Expand All @@ -171,7 +171,7 @@ public void TrySendingEmailWithNoCcAndBcc()

var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } };

var result = SMTP.SendEmail(input, Attachments, _options, default);
var result = await SMTP.SendEmail(input, Attachments, _options, default);
Assert.IsFalse(result.EmailSent);
}

Expand All @@ -191,7 +191,7 @@ public void TrySendingEmailWithNoFileAttachmentFoundException()

var Attachments = new AttachmentOptions { Attachments = new Attachment[] { attachment } };

Assert.Throws<FileNotFoundException>(() => SMTP.SendEmail(input, Attachments, _options, default));

var ex = Assert.ThrowsAsync<FileNotFoundException>(async () => await SMTP.SendEmail(input, Attachments, _options, default));
Assert.AreEqual(@$"The given filepath '{attachment.FilePath}' had no matching files", ex.Message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,36 @@ public class Attachment
/// <summary>
/// Chooses if the attachment file is created from a string or copied from disk.
/// </summary>
/// <example>AttachmentType.FileAttachment</example>
public AttachmentType AttachmentType { get; set; }

/// <summary>
/// Attachment from string.
/// </summary>
/// <example>AttachmentFromString { "Test file content", "testFile.txt" }</example>
[UIHint(nameof(AttachmentType), "", AttachmentType.AttachmentFromString)]
public AttachmentFromString StringAttachment { get; set; }

/// <summary>
/// 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.
/// </summary>
/// <example>C:\path\to\file.txt</example>
[DefaultValue("")]
[UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)]
public string FilePath { get; set; }

/// <summary>
/// If set true and no files match the given path, an exception is thrown.
/// </summary>
/// <example>true</example>
[UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)]
public bool ThrowExceptionIfAttachmentNotFound { get; set; }

/// <summary>
/// If set true and no files match the given path, email will be sent nevertheless.
/// </summary>
/// <example>true</example>
[UIHint(nameof(AttachmentType), "", AttachmentType.FileAttachment)]
public bool SendIfNoAttachmentsFound { get; set; }
}
Expand Down
11 changes: 10 additions & 1 deletion Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Input.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Frends.SMTP.SendEmail.Definitions;

Expand All @@ -11,48 +12,55 @@ public class Input
/// Recipient addresses separated by ',' or ';'
/// </summary>
/// <example>jane.doe@somedomain.com</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("jane.doe@somedomain.com")]
public string To { get; set; }

/// <summary>
/// Cc recipient addresses separated by ',' or ';'
/// </summary>
/// <example>jane.doe@somedomain.com</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("jane.doe@somedomain.com")]
public string Cc { get; set; }

/// <summary>
/// Bcc recipient addresses separated by ',' or ';'
/// </summary>
/// <example>jane.doe@somedomain.com</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("jane.doe@somedomain.com")]
public string Bcc { get; set; }

/// <summary>
/// Sender address.
/// </summary>
/// <example>jane.doe@somedomain.com</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("john.doe@somedomain.com")]
public string From { get; set; }

/// <summary>
/// Name of the sender.
/// </summary>
/// <example>Jane Doe</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("")]
public string SenderName { get; set; }

/// <summary>
/// Email message's subject.
/// </summary>
/// <example>Hello Jane</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("Hello Jane")]
public string Subject { get; set; }

/// <summary>
/// Body of the message.
/// </summary>
/// <exmaple>You've got mail!</exmaple>
/// <example>You've got mail!</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("You've got mail!")]
public string Message { get; set; }

Expand All @@ -67,6 +75,7 @@ public class Input
/// 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
/// </summary>
/// <example>utf-8</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("utf-8")]
public string MessageEncoding { get; set; }

Expand Down
30 changes: 20 additions & 10 deletions Frends.SMTP.SendEmail/Frends.Smtp.SendEmail/Definitions/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class Options
/// SMTP server address.
/// </summary>
/// <example>smtp.somedomain.com</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("smtp.somedomain.com")]
public string SMTPServer { get; set; }

Expand All @@ -23,25 +24,34 @@ public class Options
public int Port { get; set; }

/// <summary>
/// Set this true if SMTP expects to be connected using SSL.
/// Choose the SecureSocketOption to use, default is Auto
/// </summary>
/// <exmaple>true</exmaple>
[DefaultValue("false")]
public bool UseSsl { get; set; }
/// <example>SecureSocketOption.None</example>
[DefaultValue(SecureSocketOption.Auto)]
public SecureSocketOption SecureSocket { get; set; }

/// <summary>
/// Set this true if you want to use windows authentication to authenticate to SMTP server.
/// Set this true if SMTP server expectes OAuth token.
/// </summary>
/// <example>false</example>
[DefaultValue("true")]
public bool UseWindowsAuthentication { get; set; }
/// <example>true</example>
[DefaultValue(false)]
public bool UseOAuth2 { get; set; }

/// <summary>
/// Token to be used when using OAuth2.
/// </summary>
/// <example>cec4ce4f98e4f68e4vc89v1489v4987s4erv8794...</example>
[DisplayFormat(DataFormatString = "Text")]
[UIHint(nameof(UseOAuth2), "", true)]
[PasswordPropertyText]
public string Token { get; set; }

/// <summary>
/// Use this username to log in to the SMTP server
/// </summary>
/// <example>testuser</example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("")]
[UIHint(nameof(UseWindowsAuthentication), "", false)]
public string UserName { get; set; }

/// <summary>
Expand All @@ -50,6 +60,6 @@ public class Options
/// <example>Password123</example>
[PasswordPropertyText(true)]
[DefaultValue("")]
[UIHint(nameof(UseWindowsAuthentication), "", false)]
[UIHint(nameof(UseOAuth2), "", false)]
public string Password { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace Frends.SMTP.SendEmail.Definitions;

/// <summary>
/// Secure Socket Options.
/// </summary>
public enum SecureSocketOption
{
/// <summary>
/// No SSL or TLS encryption should be used.
/// </summary>
None,
/// <summary>
/// Allow the IMailService to decide which SSL or TLS options to use (default).
/// If the server does not support SSL or TLS, then the connection will continue without any encryption.
/// </summary>
Auto,
/// <summary>
/// The connection should use SSL or TLS encryption immediately.
/// </summary>
SslOnConnect,
/// <summary>
/// Elevates the connection to use TLS encryption immediately after reading the greeting and capabilities of
/// the server. If the server does not support the STARTTLS extension, then the connection will fail and a
/// NotSupportedException will be thrown.
/// </summary>
StartTls,
/// <summary>
/// Elevates the connection to use TLS encryption immediately after reading the greeting and capabilities of
/// the server, but only if the server supports the STARTTLS extension.
/// </summary>
StartTlsWhenAvailable
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>1.1.0</Version>
<Version>1.1.3</Version>
<LangVersion>latest</LangVersion>
RikuVirtanen marked this conversation as resolved.
Show resolved Hide resolved
<Authors>Frends</Authors>
<Company>Frends</Company>
Expand All @@ -24,6 +23,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="MailKit" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading
Loading