Skip to content

Instantly share code, notes, and snippets.

@promontis
Created July 29, 2023 20:23
Show Gist options
  • Save promontis/9835d43872d6f8fd964d6bbce5442628 to your computer and use it in GitHub Desktop.
Save promontis/9835d43872d6f8fd964d6bbce5442628 to your computer and use it in GitHub Desktop.
public class EmailAddress
{
public string Email { get; set; }
public string Name { get; set; }
}
public delegate Task EventHandler<TEvent>(dynamic templateData, TEvent @event, Dictionary<string, object> parameters);
public interface IMailAppender : IMailInterceptor
{
Task Append(Mail mail, Dictionary<string, object> parameters);
}
public interface IMailClient
{
Task SendMail(Mail mail);
}
public interface IMailInterceptor
{
bool Matches(string templateId, MailType type, Dictionary<string, object> parameters);
}
public interface IPublishMailCompositionEvents
{
void Subscribe<TEvent>(EventHandler<TEvent> handler);
}
public interface ISubscribeToMailCompositionEvents : IMailInterceptor
{
void Subscribe(IPublishMailCompositionEvents publisher);
}
public class Mail: IPublishMailCompositionEvents
{
private readonly IDictionary<Type, List<EventHandler<object>>> _subscriptions =
new Dictionary<Type, List<EventHandler<object>>>();
public List<EmailAddress> Tos { get; set; }
public List<EmailAddress> Ccs { get; set; }
public List<EmailAddress> Bccs { get; set; }
public EmailAddress From { get; set; }
public EmailAddress ReplyTo { get; set; }
public string Subject { get; set; }
public List<string> Categories { get; set; }
public List<MailAttachment> Attachments { get; set; }
public string TemplateId { get; }
public dynamic TemplateData { get; set; }
public MailType Type { get; }
public Mail(string templateId, MailType type)
{
TemplateId = templateId;
Type = type;
Tos = new List<EmailAddress>();
Ccs = new List<EmailAddress>();
Bccs = new List<EmailAddress>();
Attachments = new List<MailAttachment>();
Categories = new List<string>();
}
public void Subscribe<TEvent>(EventHandler<TEvent> handler)
{
if (!_subscriptions.TryGetValue(typeof(TEvent), out var handlers))
{
handlers = new List<EventHandler<object>>();
_subscriptions.Add(typeof(TEvent), handlers);
}
handlers.Add((mail, @event, parameters) => handler(mail, (TEvent)@event, parameters));
}
public void ClearSubscriptions() => _subscriptions.Clear();
}
public class MailCompositionHandler
{
private readonly IEnumerable<IMailInterceptor> _interceptors;
public MailCompositionHandler(IEnumerable<IMailInterceptor> interceptors)
{
_interceptors = interceptors;
}
public async Task<Mail> Handle(string templateId, MailType type, Dictionary<string, object> parameters)
{
var mail = new Mail(templateId, type);
var interceptors = _interceptors
.Where(interceptor => interceptor.Matches(templateId, type, parameters))
.ToList();
try
{
foreach (var subscriber in interceptors.OfType<ISubscribeToMailCompositionEvents>())
{
subscriber.Subscribe(mail);
}
var pendingTasks = new List<Task>();
foreach (var appender in interceptors.OfType<IMailAppender>())
{
pendingTasks.Add(appender.Append(mail, parameters));
}
await Task.WhenAll(pendingTasks);
return mail;
}
finally
{
mail.ClearSubscriptions();
}
}
}
public enum MailType
{
Transactional,
Marketing
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment