Appearance
Report Delivery
GrydReports supports automatic delivery of generated reports through multiple channels: Email, Webhook, and Storage. Delivery is configured per-request or per-schedule.
Delivery Methods
| Method | Enum | Description |
|---|---|---|
| Download | DeliveryMethod.Download (1) | Default — file available via download endpoint |
DeliveryMethod.Email (2) | Send report as email attachment | |
| Storage | DeliveryMethod.Storage (3) | Copy to a target path (shared drive, S3, etc.) |
| Webhook | DeliveryMethod.Webhook (4) | POST to an external URL with report metadata |
DeliveryOptions
csharp
public class DeliveryOptions
{
public DeliveryMethod Method { get; set; }
// Email
public List<string>? Recipients { get; set; }
public List<string>? CcRecipients { get; set; }
public string? EmailSubject { get; set; }
public string? EmailBody { get; set; }
// Webhook
public string? WebhookUrl { get; set; }
public Dictionary<string, string>? WebhookHeaders { get; set; }
// Storage
public string? TargetPath { get; set; }
}Email Delivery
Send reports as email attachments:
json
{
"delivery": {
"method": 2,
"recipients": ["manager@company.com", "director@company.com"],
"ccRecipients": ["archive@company.com"],
"emailSubject": "Monthly Financial Report - February 2026",
"emailBody": "Please find the attached monthly financial report."
}
}Configuration
csharp
builder.Services.ConfigureGrydReportsDelivery(opts =>
{
opts.EmailFrom = "reports@company.com";
opts.EmailFromName = "Report System";
opts.SmtpHost = "smtp.company.com";
opts.SmtpPort = 587;
opts.SmtpUseSsl = true;
opts.SmtpUsername = "smtp-user";
opts.SmtpPassword = "smtp-password";
});appsettings.json
json
{
"GrydReports": {
"EmailDelivery": {
"EmailFrom": "reports@company.com",
"EmailFromName": "Report System",
"SmtpHost": "smtp.company.com",
"SmtpPort": 587,
"SmtpUseSsl": true,
"SmtpUsername": "smtp-user",
"SmtpPassword": "smtp-password"
}
}
}Webhook Delivery
POST report metadata to an external endpoint:
json
{
"delivery": {
"method": 4,
"webhookUrl": "https://api.company.com/webhooks/reports",
"webhookHeaders": {
"Authorization": "Bearer token-123",
"X-Correlation-Id": "req-456"
}
}
}The webhook receives a POST with the following payload:
json
{
"reportId": "f47ac10b-...",
"templateId": "monthly-sales",
"format": "Pdf",
"status": "Completed",
"fileName": "monthly-sales-2026-02.pdf",
"fileSizeBytes": 245760,
"downloadUrl": "/api/v1/reports/f47ac10b-.../download",
"generatedAt": "2026-02-19T10:30:00Z"
}Webhook Configuration
csharp
builder.Services.ConfigureGrydReportsDelivery(opts =>
{
opts.WebhookTimeout = TimeSpan.FromSeconds(30);
opts.WebhookRetryCount = 3;
});Storage Delivery
Copy the generated file to a shared path:
json
{
"delivery": {
"method": 3,
"targetPath": "/shared/reports/finance/2026/"
}
}IReportDelivery Interface
Each delivery method is implemented as an IReportDelivery:
csharp
public interface IReportDelivery
{
DeliveryMethod Method { get; }
Task<Result> DeliverAsync(
ReportOutput output,
DeliveryOptions options,
CancellationToken ct = default);
}Built-in Implementations
| Class | Method | Description |
|---|---|---|
EmailReportDelivery | SMTP-based email with attachment | |
WebhookReportDelivery | Webhook | HTTP POST with report metadata |
Custom Delivery Channel
Implement IReportDelivery to add your own channel (e.g., Slack, Teams, S3):
csharp
public class SlackReportDelivery : IReportDelivery
{
public DeliveryMethod Method => DeliveryMethod.Webhook;
private readonly ISlackClient _slack;
public SlackReportDelivery(ISlackClient slack) => _slack = slack;
public async Task<Result> DeliverAsync(
ReportOutput output, DeliveryOptions options, CancellationToken ct)
{
var channel = options.WebhookUrl!; // Use webhook URL as channel
await _slack.UploadFileAsync(
channel: channel,
stream: output.Content,
fileName: output.FileName,
message: $"📊 Report ready: {output.FileName}",
cancellationToken: ct);
return Result.Success();
}
}
// Register
builder.Services.AddScoped<IReportDelivery, SlackReportDelivery>();Delivery with Scheduling
Combine delivery with scheduling for fully automated workflows:
csharp
await mediator.Send(new CreateReportScheduleCommand(
TemplateId: "daily-kpis",
Name: "Daily KPI Report",
CronExpression: "0 7 * * MON-FRI",
Format: ReportFormat.Pdf,
Delivery: new DeliveryOptions
{
Method = DeliveryMethod.Email,
Recipients = ["leadership@company.com"],
EmailSubject = "Daily KPIs - {date}",
EmailBody = "Good morning! Here are today's KPI metrics."
}
));Delivery with Async Generation
Include delivery in on-demand async generation:
bash
POST /api/v1/reports/generate-async
{
"templateId": "audit-export",
"format": 3,
"delivery": {
"method": 2,
"recipients": ["compliance@company.com"]
}
}The report is generated in background and automatically delivered when complete.
Multiple Delivery Channels
All registered IReportDelivery implementations are available. The system selects the correct one based on DeliveryOptions.Method. You can register multiple implementations for different channels.