8.1 KiB
title | description | type | page_title | slug | tags | res_type |
---|---|---|---|---|---|---|
How to Send a Telerik Report Embedded in an Email Body | Learn how to programmatically export a report to images and then embed them into the email when using web report viewers. | how-to | Sending a Telerik Report Embedded in an Email Body | send-telerik-report-embedded-email-body | telerik, reporting, email, embedded, programmatically | kb |
Environment
Property | Value |
---|---|
Product | Progress® Telerik® Reporting |
Description
I want to embed the report document inside the mail message sent by the [Send Mail Message]({%slug telerikreporting/using-reports-in-applications/display-reports-in-applications/web-application/send-mail-message%}) functionality instead of sending it as an attachment.
Solution
The default method used for sending the email is CreateMailMessage(SendDocumentArgs, DocumentData) which always returns the report document as attachment. A new method needs to be implemented to avoid that.
-
Before implementing a new endpoint, we need to create a helper class for rendering the reports to images since the report will be embedded in the email body using the img element.
public class ReportRenderer { public List streams = new(); string ReportsPath { get; set; }
public ReportRenderer(string reportsPath)
{
this.ReportsPath = reportsPath;
}
void CloseStreams()
{
foreach (Stream stream in this.streams)
{
stream.Close();
}
this.streams.Clear();
}
public Stream CreateStream(string name, string extension, Encoding encoding, string mimeType)
{
MemoryStream ms = new();
this.streams.Add(ms);
return ms;
}
public List<string> Render(ReportSourceModel reportSourceModel)
{
var list = new List<string>();
var report = Path.Combine(this.ReportsPath, reportSourceModel.Report);
var deviceInfo = new Hashtable
{
{ "OutputFormat", "PNG" }
};
Telerik.Reporting.Processing.ReportProcessor reportProcessor = new();
var reportSource = new Telerik.Reporting.UriReportSource() { Uri = report };
foreach (string key in reportSourceModel.Parameters.Keys)
{
reportSource.Parameters.Add(key, reportSourceModel.Parameters[key]);
}
bool result = reportProcessor.RenderReport("IMAGEPrintPreview", reportSource, deviceInfo, this.CreateStream, out string documentName);
foreach (MemoryStream ms in this.streams)
{
var str = Convert.ToBase64String(ms.ToArray());
list.Add(str);
}
this.CloseStreams();
return list;
}
}
1. We will also need model classes for sending the relevant email data to our endpoint.
````CSharp
public class ReportMail
{
[JsonPropertyName("to")]
public string To { get; set; }
[JsonPropertyName("from")]
public string From { get; set; }
[JsonPropertyName("cc")]
public string CC { get; set; }
[JsonPropertyName("subject")]
public string Subject { get; set; }
[JsonPropertyName("body")]
public string Body { get; set; }
[JsonPropertyName("reportSource")]
public ReportSourceModel ReportSource { get; set; }
}
public class ReportSourceModel
{
[JsonPropertyName("report")]
public string Report { get; set; }
[JsonPropertyName("parameters")]
public Dictionary<string, object> Parameters { get; set; }
}
-
To add the option for embedding the report in the send mail dialog, we also need to
override
GetDocumentFormats() endpoint and return a separate ExtensionInfo entry for the new option which in this example will be named asEmbedded
.
public override JsonResult GetDocumentFormats() { var formats = new Telerik.Reporting.Services.Engine.ExtensionInfo[6] { new() { Name = "Embedded", LocalizedName = "Embedded" }, new() { Name = "PDF", LocalizedName = "PDF Document" }, new() { Name = "CSV", LocalizedName = "CSV (comma delimited)" }, new() { Name = "DOCX", LocalizedName = "Word Document" }, new() { Name = "XLSX", LocalizedName = "Excel Worksheet" }, new() { Name = "PPTX", LocalizedName = "PowerPoint Presentation" }, }; return Json(formats); }
1. The next step is to create the new endpoint that will handle creating the images using the helper class, embed them in the body of the email, and send it.
````CSharp
[Route("cmail")]
public HttpStatusCode CustomEmailMessage([FromBody] ReportMail message)
{
using var smtpClient = new SmtpClient("SMTP_HOST", PORT);
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpClient.EnableSsl = false;
var mailMessage = GetMailWithImg(message);
smtpClient.Send(mailMessage);
return HttpStatusCode.OK;
}
private MailMessage GetMailWithImg(ReportMail message)
{
MailMessage mail = new()
{
IsBodyHtml = true,
Subject = message.Subject,
From = new MailAddress(message.From),
};
if (!string.IsNullOrEmpty(message.To))
{
mail.To.Add(message.To);
}
else throw new Exception("Please provide an email address.");
if (!string.IsNullOrEmpty(message.CC)) mail.CC.Add(message.CC);
mail.AlternateViews.Add(GetEmbeddedImage(message.Body ?? string.Empty, message.ReportSource));
return mail;
}
private AlternateView GetEmbeddedImage(string htmlBody, ReportSourceModel reportSource)
{
var reportsPath = "PATH_TO_REPORTS_FOLDER";
var reportRenderer = new ReportRenderer(reportsPath);
var images = reportRenderer.Render(reportSource);
htmlBody += "\r\n";
foreach (var image in images)
{
htmlBody += $"<img src=\"data:image/png;base64, {image}\" />";
}
AlternateView alternateView = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);
return alternateView;
}
-
The last step lies in using the [sendEmailBegin(e, args)]({%slug telerikreporting/using-reports-in-applications/display-reports-in-applications/web-application/html5-report-viewer/api-reference/reportviewer/events/sendemailbegin(e,-args)%}) to stop the default handling of the send mail functionality and instead make a fetch request to the new endpoint for the case where the selected option is
Embedded
:
$("#reportViewer1") .telerik_ReportViewer({ serviceUrl: "api/reports/", reportSource: { report: "Dashboard.trdp", }, sendEmailBegin: function ({ data }, args) {
if (args.format === "Embedded") {
args.handled = true;
const from = $('[aria-label="From email address"]').val();
const to = $('[aria-label="Recipient email address"]').val();
const cc = $('[aria-label="Carbon Copy email address"]').val();
const subject = $('[aria-label="Email subject:"]').val();
const body = $('.trv-send-email-editor textarea').data("kendoEditor").value();
const reportSource = data.sender.reportSource();
try {
fetch("/api/reports/cmail", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
from,
to,
cc,
subject,
body,
reportSource
}),
});
} catch (error) {
console.error("Error:", error);
}
}
},
sendEmail: { enabled: true }
});
## See Also
* [Generating Reports Programmatically]({%slug telerikreporting/using-reports-in-applications/call-the-report-engine-via-apis/embedded-report-engine%})
* [Send Mail Message]({%slug telerikreporting/using-reports-in-applications/display-reports-in-applications/web-application/send-mail-message%})
* [Implement Send Mail Message]({%slug telerikreporting/using-reports-in-applications/host-the-report-engine-remotely/telerik-reporting-rest-services/implement-send-mail-message%})