81 lines
3.7 KiB
C#
81 lines
3.7 KiB
C#
namespace ZB.MOM.WW.ScadaBridge.NotificationService.Ews;
|
|
|
|
/// <summary>
|
|
/// One-shot EWS mail submission (<c>CreateItem</c>, <c>SendOnly</c>, BCC-only).
|
|
/// <para>
|
|
/// The seam the central Notification Outbox's <c>EmailNotificationDeliveryAdapter</c> calls when a
|
|
/// <c>SmtpConfiguration</c> selects the EWS transport, mirroring the role
|
|
/// <c>ISmtpClientWrapper</c> plays for the SMTP transport.
|
|
/// </para>
|
|
/// </summary>
|
|
public interface IEwsMailSender
|
|
{
|
|
/// <summary>
|
|
/// Sends one message through Exchange Web Services.
|
|
/// </summary>
|
|
/// <param name="request">The endpoint, credential, sender, recipients and content to submit.</param>
|
|
/// <param name="cancellationToken">Token cancelling the send; propagates unwrapped when the caller cancels.</param>
|
|
/// <returns>A task completing when Exchange has accepted the message.</returns>
|
|
/// <exception cref="EwsPermanentException">
|
|
/// The send failed for a reason retrying cannot fix — authentication (401/403), a wrong URL
|
|
/// (404), a schema fault, or a recipient rejection.
|
|
/// </exception>
|
|
/// <exception cref="EwsTransientException">
|
|
/// The send failed for an availability-shaped reason — network/DNS/timeout, HTTP 5xx/408/429,
|
|
/// or an <c>ErrorServerBusy</c>-class response code — and is worth retrying.
|
|
/// </exception>
|
|
Task SendAsync(EwsSendRequest request, CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Everything one EWS submission needs. Carried per call rather than held on the sender so the
|
|
/// sender stays a stateless singleton and the credential never outlives the request.
|
|
/// </summary>
|
|
/// <param name="Endpoint">The absolute HTTPS EWS URL (for example <c>https://host/EWS/Exchange.asmx</c>).</param>
|
|
/// <param name="Username">The service account, which may be domain-qualified (<c>domain\user</c>).</param>
|
|
/// <param name="Password">The service account password.</param>
|
|
/// <param name="FromAddress">The sending mailbox address.</param>
|
|
/// <param name="BccRecipients">The recipients; all addressed BCC so they cannot see one another.</param>
|
|
/// <param name="Subject">The message subject.</param>
|
|
/// <param name="Body">The plain-text message body.</param>
|
|
/// <param name="TimeoutSeconds">
|
|
/// The per-request timeout; a non-positive value leaves the <see cref="HttpClient"/> default in force.
|
|
/// </param>
|
|
public sealed record EwsSendRequest(
|
|
Uri Endpoint,
|
|
string Username,
|
|
string Password,
|
|
string FromAddress,
|
|
IReadOnlyList<string> BccRecipients,
|
|
string Subject,
|
|
string Body,
|
|
int TimeoutSeconds);
|
|
|
|
/// <summary>
|
|
/// Signals an availability-shaped EWS failure that is worth retrying.
|
|
/// </summary>
|
|
public class EwsTransientException : Exception
|
|
{
|
|
/// <summary>
|
|
/// Initializes the exception with a message and optional inner exception.
|
|
/// </summary>
|
|
/// <param name="message">Message describing the transient EWS failure; never carries the credential.</param>
|
|
/// <param name="innerException">Optional underlying transport exception.</param>
|
|
public EwsTransientException(string message, Exception? innerException = null)
|
|
: base(message, innerException) { }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Signals an EWS failure that retrying cannot fix, so the notification parks immediately.
|
|
/// </summary>
|
|
public class EwsPermanentException : Exception
|
|
{
|
|
/// <summary>
|
|
/// Initializes the exception with a message and optional inner exception.
|
|
/// </summary>
|
|
/// <param name="message">Message describing the permanent EWS failure; never carries the credential.</param>
|
|
/// <param name="innerException">Optional underlying transport exception.</param>
|
|
public EwsPermanentException(string message, Exception? innerException = null)
|
|
: base(message, innerException) { }
|
|
}
|