Improved Webhook Controller Mailtrap event processing
This commit is contained in:
parent
b8bc00b68d
commit
42014a831c
|
@ -15,16 +15,15 @@ public class WebhookController(ILogger<WebhookController> logger, ApplicationDbC
|
||||||
[HttpPost("mailtrap/{apiKey}")]
|
[HttpPost("mailtrap/{apiKey}")]
|
||||||
[Authorize("EmailApi", AuthenticationSchemes = "ApiKeyInRoute")]
|
[Authorize("EmailApi", AuthenticationSchemes = "ApiKeyInRoute")]
|
||||||
public async Task<IActionResult> Mailtrap(Webhook webhook, string apiKey) {
|
public async Task<IActionResult> Mailtrap(Webhook webhook, string apiKey) {
|
||||||
|
logger.LogDebug("Start processing webhook events");
|
||||||
foreach (var webhookEvent in webhook.Events) {
|
foreach (var webhookEvent in webhook.Events) {
|
||||||
metrics.WebhookEventReceived("Mailtrap", webhookEvent.Type.ToString());
|
metrics.WebhookEventReceived("Mailtrap", webhookEvent.Type.ToString());
|
||||||
var subscriber = await context.Set<EmailSubscriber>().FirstOrDefaultAsync(s => s.Email == webhookEvent.Email);
|
var subscriber = await context.Set<EmailSubscriber>().FirstOrDefaultAsync(s => s.Email == webhookEvent.Email);
|
||||||
|
|
||||||
logger.LogDebug("Received Webhook event {EventType} for {email}",
|
logger.LogDebug("Received {WebhookEvent} event for {email}", webhookEvent.Type, webhookEvent.Email);
|
||||||
webhookEvent.Type, webhookEvent.Email);
|
|
||||||
|
|
||||||
if (subscriber is null) {
|
if (subscriber is null) {
|
||||||
logger.LogWarning(
|
logger.LogWarning(
|
||||||
"Received webhook event from mailtrap of type {EventType}, " +
|
"Received {WebhookEvent} from Mailtrap " +
|
||||||
"but failed to find subscriber with E-Mail {email}.",
|
"but failed to find subscriber with E-Mail {email}.",
|
||||||
webhookEvent.Type, webhookEvent.Email);
|
webhookEvent.Type, webhookEvent.Email);
|
||||||
metrics.WebhookEventError("Mailtrap", webhookEvent.Type.ToString(), "unknown email");
|
metrics.WebhookEventError("Mailtrap", webhookEvent.Type.ToString(), "unknown email");
|
||||||
|
@ -39,14 +38,13 @@ public class WebhookController(ILogger<WebhookController> logger, ApplicationDbC
|
||||||
case WebhookEventType.Open:
|
case WebhookEventType.Open:
|
||||||
subscriber.LastMailOpened = webhookEvent.EventDateTime;
|
subscriber.LastMailOpened = webhookEvent.EventDateTime;
|
||||||
break;
|
break;
|
||||||
case WebhookEventType.Bounce:
|
case WebhookEventType.SoftBounce:
|
||||||
// Store this message in case it develops into a suspension
|
subscriber.UnsubscribeReason = webhookEvent.Response ?? webhookEvent.Type.Humanize(LetterCasing.Title);
|
||||||
subscriber.UnsubscribeReason = webhookEvent.Response;
|
|
||||||
break;
|
break;
|
||||||
case WebhookEventType.Suspension:
|
case WebhookEventType.Suspension:
|
||||||
logger.LogWarning("Received Suspension event, you may have send from an unverifyied domain or exceeded your hourly rate.");
|
logger.LogWarning(
|
||||||
return Ok();
|
"Received Suspension event, you may have send from an unverified domain or exceeded your hourly rate.");
|
||||||
break;
|
continue;
|
||||||
case WebhookEventType.Unsubscribe:
|
case WebhookEventType.Unsubscribe:
|
||||||
subscriber.Unsubscribed = true;
|
subscriber.Unsubscribed = true;
|
||||||
subscriber.UnsubscribeReason = "User Unsubscribed";
|
subscriber.UnsubscribeReason = "User Unsubscribed";
|
||||||
|
@ -55,22 +53,23 @@ public class WebhookController(ILogger<WebhookController> logger, ApplicationDbC
|
||||||
subscriber.Unsubscribed = true;
|
subscriber.Unsubscribed = true;
|
||||||
subscriber.UnsubscribeReason = "User reported as Spam";
|
subscriber.UnsubscribeReason = "User reported as Spam";
|
||||||
break;
|
break;
|
||||||
|
case WebhookEventType.Bounce:
|
||||||
case WebhookEventType.Reject:
|
case WebhookEventType.Reject:
|
||||||
subscriber.Unsubscribed = true;
|
subscriber.Unsubscribed = true;
|
||||||
subscriber.UnsubscribeReason = webhookEvent.Reason?.Humanize().Titleize() ?? "Rejected";
|
subscriber.UnsubscribeReason = webhookEvent.Reason ?? webhookEvent.Type.Humanize(LetterCasing.Title);
|
||||||
break;
|
break;
|
||||||
case WebhookEventType.SoftBounce:
|
|
||||||
case WebhookEventType.Click:
|
case WebhookEventType.Click:
|
||||||
default:
|
default:
|
||||||
logger.LogInformation("Received unsupported event {EventType} for {email}. Skipping.", webhookEvent.Type, webhookEvent.Email);
|
logger.LogInformation("Received unsupported event {EventType} for {email}. Skipping.", webhookEvent.Type, webhookEvent.Email);
|
||||||
metrics.WebhookEventError("Mailtrap", webhookEvent.Type.ToString(), "unknown type");
|
metrics.WebhookEventError("Mailtrap", webhookEvent.Type.ToString(), "unknown type");
|
||||||
return Ok();
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
logger.LogDebug("Webhook event {EventType} for {email} processed successfully.",
|
logger.LogDebug("Webhook event {EventType} for {email} processed successfully.",
|
||||||
webhookEvent.Type, webhookEvent.Email);
|
webhookEvent.Type, webhookEvent.Email);
|
||||||
}
|
}
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
logger.LogDebug("All webhook events processed and saved");
|
||||||
|
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
using System.Text.Json.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Wave.Data.Api.Mailtrap;
|
namespace Wave.Data.Api.Mailtrap;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(JsonStringEnumConverter<WebhookEventType>))]
|
||||||
public enum WebhookEventType {
|
public enum WebhookEventType {
|
||||||
Delivery,
|
Delivery,
|
||||||
|
[EnumMember(Value = "soft bounce")]
|
||||||
SoftBounce,
|
SoftBounce,
|
||||||
Bounce,
|
Bounce,
|
||||||
Suspension,
|
Suspension,
|
||||||
Unsubscribe,
|
Unsubscribe,
|
||||||
Open,
|
Open,
|
||||||
|
[EnumMember(Value = "spam complaint")]
|
||||||
SpamComplaint,
|
SpamComplaint,
|
||||||
Click,
|
Click,
|
||||||
Reject
|
Reject
|
||||||
|
@ -34,7 +38,7 @@ public record WebhookEvent(
|
||||||
[property:JsonPropertyName("response_code")]
|
[property:JsonPropertyName("response_code")]
|
||||||
int? ResponseCode) {
|
int? ResponseCode) {
|
||||||
|
|
||||||
public WebhookEventType Type => Enum.Parse<WebhookEventType>(EventTypeString.Replace("_", ""), true);
|
public WebhookEventType Type => Enum.Parse<WebhookEventType>(EventTypeString.Replace("_", "").Replace(" ", ""), true);
|
||||||
public DateTimeOffset EventDateTime => DateTimeOffset.FromUnixTimeSeconds(Timestamp);
|
public DateTimeOffset EventDateTime => DateTimeOffset.FromUnixTimeSeconds(Timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue