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

Provide enum for Action field #21

Open
rklec opened this issue Sep 25, 2024 · 0 comments
Open

Provide enum for Action field #21

rklec opened this issue Sep 25, 2024 · 0 comments

Comments

@rklec
Copy link
Contributor

rklec commented Sep 25, 2024

The Action currently is a string. For a programmer, an enum would maybe be more helpful.

https://www.rfc-editor.org/rfc/rfc3464#section-2.3.3 defines the values of it. As this s an exclusive (aka terminal) list, it cannot contain more/other entries and it must be contained in a DSN.

So AFAIK it should be safe to parse in an enum?

You can then C# doc it to explain what the status means.

E.g. like this:

/// <summary>
/// An enum containing the DSN (delivery status notification) action field values, as per <em>RFC 3464</em>.
/// </summary>
/// <remarks><see href="https://www.rfc-editor.org/rfc/rfc3464#section-2.3.3"/></remarks>
public enum DsnAction
{
    /// <summary>
    /// "indicates that the message could not be delivered to the
    /// recipient.  The Reporting MTA has abandoned any attempts
    /// to deliver the message to this recipient.  No further
    /// notifications should be expected."
    /// </summary>
    Failed,
    
    /// <summary>
    /// "indicates that the Reporting MTA has so far been unable
    /// to deliver or relay the message, but it will continue to
    /// attempt to do so.  Additional notification messages may
    /// be issued as the message is further delayed or
    /// successfully delivered, or if delivery attempts are later
    /// abandoned."
    /// </summary>
    Delayed,
    
    /// <summary>
    /// "indicates that the message was successfully delivered to
    /// the recipient address specified by the sender, which
    /// includes "delivery" to a mailing list exploder.  It does
    /// not indicate that the message has been read.  This is a
    /// terminal state and no further DSN for this recipient
    /// should be expected."
    /// </summary>
    Delivered,
    
    /// <summary>
    /// "indicates that the message has been relayed or gatewayed
    /// into an environment that does not accept responsibility
    /// for generating DSNs upon successful delivery.  This
    /// action-value SHOULD NOT be used unless the sender has
    /// requested notification of successful delivery for this
    /// recipient."
    /// </summary>
    Relayed,
    
    /// <summary>
    /// "indicates that the message has been successfully
    /// delivered to the recipient address as specified by the
    /// sender, and forwarded by the Reporting-MTA beyond that
    /// destination to multiple additional recipient addresses.
    /// An action-value of "expanded" differs from "delivered" in
    /// that "expanded" is not a terminal state.  Further
    /// "failed" and/or "delayed" notifications may be provided."
    /// </summary>
    Expanded,
}

Care must just be taken to parse it case-insensitively, as the RFC says:

The action-value may be spelled in any combination of upper and lower
case characters.

Parsing could e.g. be done in a class like this:

public class DsnActionLookup
{
    private readonly Dictionary<string, DsnAction> actions = new(StringComparer.OrdinalIgnoreCase)
    {
        { "failed", DsnAction.Failed },
        { "delayed", DsnAction.Delayed },
        { "delivered", DsnAction.Delivered },
        { "relayed", DsnAction.Relayed },
        { "expanded", DsnAction.Expanded }
    };

    /// <summary>
    /// Tries to get the <see cref="DsnAction"/> corresponding to the given action string.
    /// </summary>
    /// <param name="action">The action string to compare.</param>
    /// <param name="dsnAction">The resulting <see cref="DsnAction"/> if found.</param>
    /// <returns><c>true</c> if the action string matched; otherwise, <c>false</c>.</returns>
    public bool TryGetDsnAction(string action, out DsnAction dsnAction)
    {
        return actions.TryGetValue(action, out dsnAction);
    }

    /// <summary>
    /// Indexer to retrieve the <see cref="DsnAction"/> corresponding to the given action string.
    /// </summary>
    /// <param name="action">The action string to compare.</param>
    /// <exception cref="KeyNotFoundException">Thrown when the action string does not exist in the lookup.</exception>
    /// <returns>The <see cref="DsnAction"/> corresponding to the provided action string.</returns>
    public DsnAction this[string action] => actions[action];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant