-
-
Notifications
You must be signed in to change notification settings - Fork 17
Add combined protocol auth helpers for tooling #595
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
Changes from 1 commit
85b97b9
c26a5a0
0c5d243
0614699
876adc1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -76,6 +76,11 @@ public string? PendingMessagesPath { | |
| /// <summary>Credentials used during authentication.</summary> | ||
| public NetworkCredential? Credential { get; private set; } | ||
|
|
||
| /// <summary> | ||
| /// Effective secure socket options used by the active or most recent connection attempt. | ||
| /// </summary> | ||
| public SecureSocketOptions ActiveSecureSocketOptions => _activeSecureSocketOptions; | ||
|
|
||
| /// <summary> | ||
| /// Optional identity hint used to isolate SMTP connection pooling by credentials. | ||
| /// </summary> | ||
|
|
@@ -590,6 +595,58 @@ public async Task<SmtpResult> ConnectAsync(string server, int port, SecureSocket | |
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Connects and authenticates using the provided user name/secret in one step. | ||
| /// </summary> | ||
| /// <param name="server">SMTP server hostname.</param> | ||
| /// <param name="port">SMTP server port.</param> | ||
| /// <param name="userName">SMTP user name.</param> | ||
| /// <param name="secret">SMTP password or OAuth token.</param> | ||
| /// <param name="secureSocketOptions">TLS/SSL options.</param> | ||
| /// <param name="useSsl">Compatibility SSL switch.</param> | ||
| /// <param name="authMode">Authentication mode.</param> | ||
| /// <param name="cancellationToken">Cancellation token.</param> | ||
| /// <returns>Combined connect/auth outcome.</returns> | ||
| public async Task<SmtpConnectAuthenticateResult> ConnectAndAuthenticateAsync( | ||
| string server, | ||
| int port, | ||
| string userName, | ||
| string secret, | ||
| SecureSocketOptions secureSocketOptions = SecureSocketOptions.Auto, | ||
| bool useSsl = false, | ||
| ProtocolAuthMode authMode = ProtocolAuthMode.Basic, | ||
| CancellationToken cancellationToken = default) { | ||
| var connectResult = await ConnectAsync(server, port, secureSocketOptions, useSsl).ConfigureAwait(false); | ||
|
||
| if (!connectResult.Status) { | ||
| return new SmtpConnectAuthenticateResult { | ||
| IsSuccess = false, | ||
| SecureSocketOptions = ActiveSecureSocketOptions, | ||
| ErrorCode = "connect_failed", | ||
| Error = connectResult.Error ?? "Connect failed.", | ||
| IsTransient = true | ||
|
||
| }; | ||
| } | ||
|
|
||
| try { | ||
| await ProtocolAuth.AuthenticateSmtpAsync(Client, userName, secret, authMode, cancellationToken).ConfigureAwait(false); | ||
|
||
| Credential = new NetworkCredential(userName?.Trim() ?? string.Empty, secret ?? string.Empty); | ||
| return new SmtpConnectAuthenticateResult { | ||
| IsSuccess = true, | ||
| SecureSocketOptions = ActiveSecureSocketOptions | ||
| }; | ||
| } catch (OperationCanceledException) { | ||
| throw; | ||
| } catch (Exception ex) { | ||
| return new SmtpConnectAuthenticateResult { | ||
PrzemyslawKlys marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| IsSuccess = false, | ||
| SecureSocketOptions = ActiveSecureSocketOptions, | ||
| ErrorCode = "auth_failed", | ||
| Error = ex.Message, | ||
| IsTransient = false | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Authenticate using the provided credentials. | ||
| /// </summary> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| using MailKit.Security; | ||
|
|
||
| namespace Mailozaurr; | ||
|
|
||
| /// <summary> | ||
| /// Result of connecting and authenticating an SMTP session. | ||
| /// </summary> | ||
| public sealed class SmtpConnectAuthenticateResult { | ||
| /// <summary> | ||
| /// True when both connect and authenticate succeeded. | ||
| /// </summary> | ||
| public bool IsSuccess { get; init; } | ||
|
|
||
| /// <summary> | ||
| /// Effective secure socket options used for the connection. | ||
| /// </summary> | ||
| public SecureSocketOptions SecureSocketOptions { get; init; } = SecureSocketOptions.Auto; | ||
|
|
||
| /// <summary> | ||
| /// Stable error code for connect/auth failures. | ||
| /// </summary> | ||
| public string ErrorCode { get; init; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Human-readable error text. | ||
| /// </summary> | ||
| public string Error { get; init; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// True when the failure is likely transient. | ||
| /// </summary> | ||
| public bool IsTransient { get; init; } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
cancellationTokenparameter is documented for the combined operation, but the method startsConnectAsync(...)without checking the token first, so an already-canceled call can still open a network connection before cancellation is observed during authentication. This violates caller expectations for cooperative cancellation and can trigger side effects after cancellation was requested.Useful? React with 👍 / 👎.