Add CC and BCC to emails

This commit is contained in:
Nicolas Dorier
2025-11-08 22:42:45 +09:00
parent d7fcd55707
commit dcf60e20b9
16 changed files with 442 additions and 177 deletions

View File

@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
@@ -53,7 +53,7 @@ public class WebhooksPlugin : BaseBTCPayServerPlugin
AddPendingTransactionWebhooks(services);
}
private static void AddPendingTransactionWebhooks(IServiceCollection services)
private static void AddPendingTransactionWebhooks(IServiceCollection services)
{
services.AddWebhookTriggerProvider<PendingTransactionTriggerProvider>();
var pendingTransactionsPlaceholders = new List<EmailTriggerViewModel.PlaceHolder>()
@@ -73,32 +73,45 @@ public class WebhooksPlugin : BaseBTCPayServerPlugin
{
Trigger = PendingTransactionTriggerProvider.PendingTransactionCreated,
Description = "Pending Transaction - Created",
SubjectExample = "Pending Transaction {PendingTransaction.TrimmedId} Created",
BodyExample = "Review the transaction {PendingTransaction.Id} and sign it on: {PendingTransaction.Link}",
DefaultEmail = new()
{
Subject = "Pending Transaction {PendingTransaction.TrimmedId} Created",
Body = "Review the transaction {PendingTransaction.Id} and sign it on: {PendingTransaction.Link}"
},
PlaceHolders = pendingTransactionsPlaceholders
},
new()
{
Trigger = PendingTransactionTriggerProvider.PendingTransactionSignatureCollected,
Description = "Pending Transaction - Signature Collected",
SubjectExample = "Signature Collected for Pending Transaction {PendingTransaction.TrimmedId}",
BodyExample = "So far {PendingTransaction.SignaturesCollected} signatures collected out of {PendingTransaction.SignaturesNeeded} signatures needed. ",
DefaultEmail = new()
{
Subject = "Signature Collected for Pending Transaction {PendingTransaction.TrimmedId}",
Body =
"So far {PendingTransaction.SignaturesCollected} signatures collected out of {PendingTransaction.SignaturesNeeded} signatures needed. "
},
PlaceHolders = pendingTransactionsPlaceholders
},
new()
{
Trigger = PendingTransactionTriggerProvider.PendingTransactionBroadcast,
Description = "Pending Transaction - Broadcast",
SubjectExample = "Transaction {PendingTransaction.TrimmedId} has been Broadcast",
BodyExample = "Transaction is visible in mempool on: https://mempool.space/tx/{PendingTransaction.Id}. ",
DefaultEmail = new()
{
Subject = "Transaction {PendingTransaction.TrimmedId} has been Broadcast",
Body = "Transaction is visible in mempool on: https://mempool.space/tx/{PendingTransaction.Id}. "
},
PlaceHolders = pendingTransactionsPlaceholders
},
new()
{
Trigger = PendingTransactionTriggerProvider.PendingTransactionCancelled,
Description = "Pending Transaction - Cancelled",
SubjectExample = "Pending Transaction {PendingTransaction.TrimmedId} Cancelled",
BodyExample = "Transaction {PendingTransaction.Id} is cancelled and signatures are no longer being collected. ",
DefaultEmail = new()
{
Subject = "Pending Transaction {PendingTransaction.TrimmedId} Cancelled",
Body = "Transaction {PendingTransaction.Id} is cancelled and signatures are no longer being collected. "
},
PlaceHolders = pendingTransactionsPlaceholders
}
};
@@ -130,46 +143,61 @@ public class WebhooksPlugin : BaseBTCPayServerPlugin
{
Trigger = WebhookEventType.PaymentRequestCreated,
Description = "Payment Request - Created",
SubjectExample = "Payment Request {PaymentRequest.Id} created",
BodyExample = "Payment Request {PaymentRequest.Id} ({PaymentRequest.Title}) created.",
PlaceHolders = paymentRequestPlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Payment Request {PaymentRequest.Id} created",
Body = "Payment Request {PaymentRequest.Id} ({PaymentRequest.Title}) created.",
CanIncludeCustomerEmail = true
},
PlaceHolders = paymentRequestPlaceholders
},
new()
{
Trigger = WebhookEventType.PaymentRequestUpdated,
Description = "Payment Request - Updated",
SubjectExample = "Payment Request {PaymentRequest.Id} updated",
BodyExample = "Payment Request {PaymentRequest.Id} ({PaymentRequest.Title}) updated.",
PlaceHolders = paymentRequestPlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Payment Request {PaymentRequest.Id} updated",
Body = "Payment Request {PaymentRequest.Id} ({PaymentRequest.Title}) updated.",
CanIncludeCustomerEmail = true
},
PlaceHolders = paymentRequestPlaceholders
},
new()
{
Trigger = WebhookEventType.PaymentRequestArchived,
Description = "Payment Request - Archived",
SubjectExample = "Payment Request {PaymentRequest.Id} archived",
BodyExample = "Payment Request {PaymentRequest.Id} ({PaymentRequest.Title}) archived.",
PlaceHolders = paymentRequestPlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Payment Request {PaymentRequest.Id} archived",
Body = "Payment Request {PaymentRequest.Id} ({PaymentRequest.Title}) archived.",
CanIncludeCustomerEmail = true
},
PlaceHolders = paymentRequestPlaceholders
},
new()
{
Trigger = WebhookEventType.PaymentRequestStatusChanged,
Description = "Payment Request - Status Changed",
SubjectExample = "Payment Request {PaymentRequest.Id} status changed",
BodyExample = "Payment Request {PaymentRequest.Id} ({PaymentRequest.Title}) status changed to {PaymentRequest.Status}.",
PlaceHolders = paymentRequestPlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Payment Request {PaymentRequest.Id} status changed",
Body = "Payment Request {PaymentRequest.Id} ({PaymentRequest.Title}) status changed to {PaymentRequest.Status}.",
CanIncludeCustomerEmail = true
},
PlaceHolders = paymentRequestPlaceholders
},
new()
{
Trigger = WebhookEventType.PaymentRequestCompleted,
Description = "Payment Request - Completed",
SubjectExample = "Payment Request {PaymentRequest.Title} {PaymentRequest.ReferenceId} Completed",
BodyExample = "The total of {PaymentRequest.Amount} {PaymentRequest.Currency} has been received and Payment Request {PaymentRequest.Id} is completed.\nReview the payment request: {PaymentRequest.Link}",
PlaceHolders = paymentRequestPlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Payment Request {PaymentRequest.Title} {PaymentRequest.ReferenceId} Completed",
Body = "The total of {PaymentRequest.Amount} {PaymentRequest.Currency} has been received and Payment Request {PaymentRequest.Id} is completed.\nReview the payment request: {PaymentRequest.Link}",
CanIncludeCustomerEmail = true
},
PlaceHolders = paymentRequestPlaceholders
}
};
services.AddWebhookTriggerViewModels(paymentRequestTriggers);
@@ -192,24 +220,33 @@ public class WebhooksPlugin : BaseBTCPayServerPlugin
{
Trigger = WebhookEventType.PayoutCreated,
Description = "Payout - Created",
SubjectExample = "Payout {Payout.Id} created",
BodyExample = "Payout {Payout.Id} (Pull Payment Id: {Payout.PullPaymentId}) created.",
DefaultEmail = new()
{
Subject = "Payout {Payout.Id} created",
Body = "Payout {Payout.Id} (Pull Payment Id: {Payout.PullPaymentId}) created."
},
PlaceHolders = payoutPlaceholders
},
new()
{
Trigger = WebhookEventType.PayoutApproved,
Description = "Payout - Approved",
SubjectExample = "Payout {Payout.Id} approved",
BodyExample = "Payout {Payout.Id} (Pull Payment Id: {Payout.PullPaymentId}) approved.",
DefaultEmail = new()
{
Subject = "Payout {Payout.Id} approved",
Body = "Payout {Payout.Id} (Pull Payment Id: {Payout.PullPaymentId}) approved."
},
PlaceHolders = payoutPlaceholders
},
new()
{
Trigger = WebhookEventType.PayoutUpdated,
Description = "Payout - Updated",
SubjectExample = "Payout {Payout.Id} updated",
BodyExample = "Payout {Payout.Id} (Pull Payment Id: {Payout.PullPaymentId}) updated.",
DefaultEmail = new()
{
Subject = "Payout {Payout.Id} updated",
Body = "Payout {Payout.Id} (Pull Payment Id: {Payout.PullPaymentId}) updated."
},
PlaceHolders = payoutPlaceholders
}
};
@@ -238,82 +275,110 @@ public class WebhooksPlugin : BaseBTCPayServerPlugin
{
Trigger = WebhookEventType.InvoiceCreated,
Description = "Invoice - Created",
SubjectExample = "Invoice {Invoice.Id} created",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) created.",
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} created",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) created.",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders
},
new()
{
Trigger = WebhookEventType.InvoiceReceivedPayment,
Description = "Invoice - Received Payment",
SubjectExample = "Invoice {Invoice.Id} received payment",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) received payment.",
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} received payment",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) received payment.",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders
},
new()
{
Trigger = WebhookEventType.InvoiceProcessing,
Description = "Invoice - Is Processing",
SubjectExample = "Invoice {Invoice.Id} processing",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) is processing.",
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} processing",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) is processing.",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders
},
new()
{
Trigger = WebhookEventType.InvoiceExpired,
Description = "Invoice - Expired",
SubjectExample = "Invoice {Invoice.Id} expired",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) expired.",
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} expired",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) expired.",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders
},
new()
{
Trigger = WebhookEventType.InvoiceSettled,
Description = "Invoice - Is Settled",
SubjectExample = "Invoice {Invoice.Id} settled",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) is settled.",
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} settled",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) is settled.",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders
},
new()
{
Trigger = WebhookEventType.InvoiceInvalid,
Description = "Invoice - Became Invalid",
SubjectExample = "Invoice {Invoice.Id} invalid",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) invalid.",
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} invalid",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) invalid.",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders
},
new()
{
Trigger = WebhookEventType.InvoicePaymentSettled,
Description = "Invoice - Payment Settled",
SubjectExample = "Invoice {Invoice.Id} payment settled",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) payment settled.",
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} payment settled",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) payment settled.",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders
},
new()
{
Trigger = WebhookEventType.InvoiceExpiredPaidPartial,
Description = "Invoice - Expired Paid Partial",
SubjectExample = "Invoice {Invoice.Id} expired with partial payment",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) expired with partial payment. \nPlease review and take appropriate action: {Invoice.Link}",
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} expired with partial payment",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) expired with partial payment. \nPlease review and take appropriate action: {Invoice.Link}",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
},
new()
{
Trigger = WebhookEventType.InvoicePaidAfterExpiration,
Description = "Invoice - Expired Paid Late",
SubjectExample = "Invoice {Invoice.Id} paid after expiration",
BodyExample = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) paid after expiration.",
PlaceHolders = invoicePlaceholders,
CanIncludeCustomerEmail = true
DefaultEmail = new()
{
Subject = "Invoice {Invoice.Id} paid after expiration",
Body = "Invoice {Invoice.Id} (Order Id: {Invoice.OrderId}) paid after expiration.",
CanIncludeCustomerEmail = true
},
PlaceHolders = invoicePlaceholders
}
};
services.AddWebhookTriggerViewModels(emailTriggers);