如何在 .NET 中将 PDF 转换为图像
自动化文档交付几乎是每个业务线 .NET 应用程序都会遇到的需求。 订单生成后,发票必须在几秒钟内送达客户。 如果报告是在夜间生成的,利益相关者希望在上班前就能在邮箱里收到。最简单、最通用的交付格式是将PDF文件作为电子邮件附件发送。 本指南将引导您完成C#的完整端到端工作流程——在内存中使用IronPDF生成PDF文档,然后通过MailKit或内置的System.Net.Mail命名空间将其作为电子邮件附件发送,而无需将单个字节写入磁盘。
如何安装所需的软件包?
该工作流程由两个软件包驱动:PDF 生成库和电子邮件发送库。 可以通过 Visual Studio 中的程序包管理器控制台或通过 .NET CLI 安装两者。
Install-Package IronPdf, MailKit
IronPDF 采用基于 Chromium 的渲染引擎,可将 HTML、CSS 和 JavaScript 转换为像素级完美的 PDF 文档。 它可以运行在 Windows、Linux 和 macOS 上,这意味着相同的代码可以在 ASP.NET Core Web API、后台服务或 Azure 函数中使用。 MailKit 是微软推荐用于所有新的 .NET 电子邮件开发的库——它支持 SMTP、IMAP、POP3、OAuth 2.0 和完整的 MIME 构造。 MailKit 的源代码和文档可在 GitHub 上找到。
如何在内存中生成 PDF 文档?
ChromePdfRenderer类是HTML转PDF转换的入口点。 将HTML字符串传递给PdfDocument对象。 通过BinaryData属性访问原始字节——这个字节数组正是电子邮件附件API所期望的。
using IronPdf;
var renderer = new ChromePdfRenderer();
string htmlContent = """
<h1>Order Confirmation</h1>
<p>Thank you for your purchase.</p>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th></tr>
<tr><td>Widget A</td><td>2</td><td>$19.99</td></tr>
<tr><td>Widget B</td><td>1</td><td>$59.99</td></tr>
</table>
<p><strong>Order Total: $99.97</strong></p>
""";
PdfDocument pdf = renderer.RenderHtmlAsPdf(htmlContent);
// pdf.BinaryData holds the complete PDF as a byte array
byte[] pdfBytes = pdf.BinaryData;
Console.WriteLine($"PDF generated: {pdfBytes.Length} bytes");
using IronPdf;
var renderer = new ChromePdfRenderer();
string htmlContent = """
<h1>Order Confirmation</h1>
<p>Thank you for your purchase.</p>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th></tr>
<tr><td>Widget A</td><td>2</td><td>$19.99</td></tr>
<tr><td>Widget B</td><td>1</td><td>$59.99</td></tr>
</table>
<p><strong>Order Total: $99.97</strong></p>
""";
PdfDocument pdf = renderer.RenderHtmlAsPdf(htmlContent);
// pdf.BinaryData holds the complete PDF as a byte array
byte[] pdfBytes = pdf.BinaryData;
Console.WriteLine($"PDF generated: {pdfBytes.Length} bytes");
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim htmlContent As String = "
<h1>Order Confirmation</h1>
<p>Thank you for your purchase.</p>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th></tr>
<tr><td>Widget A</td><td>2</td><td>$19.99</td></tr>
<tr><td>Widget B</td><td>1</td><td>$59.99</td></tr>
</table>
<p><strong>Order Total: $99.97</strong></p>
"
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(htmlContent)
' pdf.BinaryData holds the complete PDF as a byte array
Dim pdfBytes As Byte() = pdf.BinaryData
Console.WriteLine($"PDF generated: {pdfBytes.Length} bytes")
RenderHtmlAsPdf方法使用与谷歌Chrome相同的Chromium引擎解析HTML,因此表格、CSS网格、Flexbox和嵌入字体在浏览器中呈现的效果完全一致。 结果是BinaryData属性返回完整的PDF二进制,无需任何磁盘读写。 对于需要引入外部图像或样式表的文档,请使用可选的BasePath参数来告诉IronPDF在哪里解析相对资源URL——在HTML文件转PDF指南页中对此进行了详细介绍。
设置页面布局和自定义页眉
在附加 PDF 文件之前,您可能需要配置页边距、页眉或页脚。 所有布局选项都存储在RenderingOptions属性上:
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.MarginTop = 15;
renderer.RenderingOptions.MarginBottom = 15;
renderer.RenderingOptions.MarginLeft = 12;
renderer.RenderingOptions.MarginRight = 12;
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div style='font-size:9pt;color:#666;text-align:right;'>Monthly Report</div>",
DrawDividerLine = true
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div style='font-size:8pt;text-align:center;'>{page} of {total-pages}</div>"
};
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Monthly Summary</h1><p>See attached data.</p>");
byte[] pdfBytes = pdf.BinaryData;
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.MarginTop = 15;
renderer.RenderingOptions.MarginBottom = 15;
renderer.RenderingOptions.MarginLeft = 12;
renderer.RenderingOptions.MarginRight = 12;
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div style='font-size:9pt;color:#666;text-align:right;'>Monthly Report</div>",
DrawDividerLine = true
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div style='font-size:8pt;text-align:center;'>{page} of {total-pages}</div>"
};
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Monthly Summary</h1><p>See attached data.</p>");
byte[] pdfBytes = pdf.BinaryData;
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.MarginTop = 15
renderer.RenderingOptions.MarginBottom = 15
renderer.RenderingOptions.MarginLeft = 12
renderer.RenderingOptions.MarginRight = 12
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter With {
.HtmlFragment = "<div style='font-size:9pt;color:#666;text-align:right;'>Monthly Report</div>",
.DrawDividerLine = True
}
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.HtmlFragment = "<div style='font-size:8pt;text-align:center;'>{page} of {total-pages}</div>"
}
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>Monthly Summary</h1><p>See attached data.</p>")
Dim pdfBytes As Byte() = pdf.BinaryData
边距以毫米为单位。 {total-pages}令牌在渲染时被替换。HTML字符串转PDF指南页涵盖了完整的渲染选项集。 您还可以在附加之前,在生成的文档上添加水印或图文印章。
如何使用 MailKit 将 PDF 文件附加到电子邮件中?
MailKit 直接构建 MIME 邮件树,让您可以完全控制内容类型、编码和附件元数据。 BodyBuilder助手类简化了带有一个或多个文件附件的文本或HTML正文的常见情况。
using IronPdf;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
// Step 1 -- generate the PDF in memory
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Monthly Report</h1><p>Generated automatically.</p>");
// Step 2 -- build the email message
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Reports Service", "reports@example.com"));
message.To.Add(new MailboxAddress("Alice Smith", "alice@example.com"));
message.Subject = "Your Monthly Report is Ready";
var builder = new BodyBuilder();
builder.TextBody = "Hello Alice,\n\nPlease find your monthly report attached.\n\nRegards,\nReports Service";
builder.HtmlBody = "<p>Hello Alice,</p><p>Please find your monthly report attached.</p>";
// Add the in-memory PDF as an attachment
builder.Attachments.Add("MonthlyReport.pdf", pdf.BinaryData, new ContentType("application", "pdf"));
message.Body = builder.ToMessageBody();
// Step 3 -- send via SMTP with TLS
using var client = new SmtpClient();
await client.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
await client.AuthenticateAsync("username", "app-password");
await client.SendAsync(message);
await client.DisconnectAsync(true);
using IronPdf;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
// Step 1 -- generate the PDF in memory
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Monthly Report</h1><p>Generated automatically.</p>");
// Step 2 -- build the email message
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Reports Service", "reports@example.com"));
message.To.Add(new MailboxAddress("Alice Smith", "alice@example.com"));
message.Subject = "Your Monthly Report is Ready";
var builder = new BodyBuilder();
builder.TextBody = "Hello Alice,\n\nPlease find your monthly report attached.\n\nRegards,\nReports Service";
builder.HtmlBody = "<p>Hello Alice,</p><p>Please find your monthly report attached.</p>";
// Add the in-memory PDF as an attachment
builder.Attachments.Add("MonthlyReport.pdf", pdf.BinaryData, new ContentType("application", "pdf"));
message.Body = builder.ToMessageBody();
// Step 3 -- send via SMTP with TLS
using var client = new SmtpClient();
await client.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
await client.AuthenticateAsync("username", "app-password");
await client.SendAsync(message);
await client.DisconnectAsync(true);
Imports IronPdf
Imports MailKit.Net.Smtp
Imports MailKit.Security
Imports MimeKit
' Step 1 -- generate the PDF in memory
Dim renderer As New ChromePdfRenderer()
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>Monthly Report</h1><p>Generated automatically.</p>")
' Step 2 -- build the email message
Dim message As New MimeMessage()
message.From.Add(New MailboxAddress("Reports Service", "reports@example.com"))
message.To.Add(New MailboxAddress("Alice Smith", "alice@example.com"))
message.Subject = "Your Monthly Report is Ready"
Dim builder As New BodyBuilder()
builder.TextBody = "Hello Alice," & vbCrLf & vbCrLf & "Please find your monthly report attached." & vbCrLf & vbCrLf & "Regards," & vbCrLf & "Reports Service"
builder.HtmlBody = "<p>Hello Alice,</p><p>Please find your monthly report attached.</p>"
' Add the in-memory PDF as an attachment
builder.Attachments.Add("MonthlyReport.pdf", pdf.BinaryData, New ContentType("application", "pdf"))
message.Body = builder.ToMessageBody()
' Step 3 -- send via SMTP with TLS
Using client As New SmtpClient()
Await client.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls)
Await client.AuthenticateAsync("username", "app-password")
Await client.SendAsync(message)
Await client.DisconnectAsync(True)
End Using
ContentType实例。 异步 SMTP 方法在网络操作完成时保持调用线程空闲——这对于处理数十个并发请求的 ASP.NET Core 控制器至关重要。
AuthenticateAsync。 对于Microsoft 365,如果您的租户禁用了基本认证,请通过MailKit的SaslMechanismOAuth2类配置OAuth 2.0认证。
发送给多个收件人
要在同一封电子邮件中抄送多人,请在调用Bcc集合中:
message.To.Add(new MailboxAddress("Alice Smith", "alice@example.com"));
message.To.Add(new MailboxAddress("Bob Jones", "bob@example.com"));
message.Cc.Add(new MailboxAddress("Carol Manager", "carol@example.com"));
message.To.Add(new MailboxAddress("Alice Smith", "alice@example.com"));
message.To.Add(new MailboxAddress("Bob Jones", "bob@example.com"));
message.Cc.Add(new MailboxAddress("Carol Manager", "carol@example.com"));
message.To.Add(New MailboxAddress("Alice Smith", "alice@example.com"))
message.To.Add(New MailboxAddress("Bob Jones", "bob@example.com"))
message.Cc.Add(New MailboxAddress("Carol Manager", "carol@example.com"))
单次SendAsync调用将消息发送到所有地址。 MailKit 在一个 SMTP 会话中批量处理 RCPT TO 命令,因此对于多个收件人不会造成性能损失。
如何使用 System.Net.Mail 作为替代方案?
对于面向旧.NET版本的项目或不允许添加第三方NuGet包的项目,内置的System.Net.Mail命名空间可以处理基本SMTP传输。 微软不再建议在新开发项目中使用它,但它涵盖了常见的用例,而且没有额外的依赖项。
using IronPdf;
using System.Net;
using System.Net.Mail;
// Generate the PDF
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Amount due: $350.00</p>");
// Build the mail message
using var message = new MailMessage("invoices@example.com", "customer@example.com");
message.Subject = "Invoice #1001 Attached";
message.Body = "Your invoice is attached to this email. Please remit payment within 30 days.";
message.IsBodyHtml = false;
// Wrap the byte array in a MemoryStream for the Attachment constructor
var stream = new MemoryStream(pdf.BinaryData);
message.Attachments.Add(new Attachment(stream, "Invoice-1001.pdf", "application/pdf"));
// Send via SMTP
using var client = new SmtpClient("smtp.example.com", 587)
{
Credentials = new NetworkCredential("username", "password"),
EnableSsl = true
};
await client.SendMailAsync(message);
using IronPdf;
using System.Net;
using System.Net.Mail;
// Generate the PDF
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Amount due: $350.00</p>");
// Build the mail message
using var message = new MailMessage("invoices@example.com", "customer@example.com");
message.Subject = "Invoice #1001 Attached";
message.Body = "Your invoice is attached to this email. Please remit payment within 30 days.";
message.IsBodyHtml = false;
// Wrap the byte array in a MemoryStream for the Attachment constructor
var stream = new MemoryStream(pdf.BinaryData);
message.Attachments.Add(new Attachment(stream, "Invoice-1001.pdf", "application/pdf"));
// Send via SMTP
using var client = new SmtpClient("smtp.example.com", 587)
{
Credentials = new NetworkCredential("username", "password"),
EnableSsl = true
};
await client.SendMailAsync(message);
Imports IronPdf
Imports System.Net
Imports System.Net.Mail
Imports System.IO
' Generate the PDF
Dim renderer As New ChromePdfRenderer()
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Amount due: $350.00</p>")
' Build the mail message
Using message As New MailMessage("invoices@example.com", "customer@example.com")
message.Subject = "Invoice #1001 Attached"
message.Body = "Your invoice is attached to this email. Please remit payment within 30 days."
message.IsBodyHtml = False
' Wrap the byte array in a MemoryStream for the Attachment constructor
Dim stream As New MemoryStream(pdf.BinaryData)
message.Attachments.Add(New Attachment(stream, "Invoice-1001.pdf", "application/pdf"))
' Send via SMTP
Using client As New SmtpClient("smtp.example.com", 587)
client.Credentials = New NetworkCredential("username", "password")
client.EnableSsl = True
Await client.SendMailAsync(message)
End Using
End Using
与MailKit相比的关键区别在于using语句中,这些语句在发送后会释放SMTP连接并刷新基础流。 如果在using,附件流可能会在某些运行环境中发送完成之前被释放。
在 MailKit 和 System.Net.Mail 之间进行选择
| 特征 | MailKit | System.Net.Mail |
|---|---|---|
| OAuth 2.0 身份验证 | 是 | 无 |
| IMAP/POP3 支持 | 是 | 无 |
| 异步优先 API | 是 | 部分的 |
| 微软推荐 | 受到推崇的 | 遗产 |
| 附加 NuGet 包 | 必需的 | 无需 |
| 复杂的 MIME 构造 | 全面支持 | 基础 |
对于任何新项目,请选择 MailKit,尤其是在 SMTP 服务器需要 OAuth 或需要 IMAP 读取回复的情况下。 在代码库已经依赖于它且迁移成本不被证明合理时使用System.Net.Mail。
如何将此模式应用于实际业务工作流程?
内存中 PDF 转电子邮件模式直接适用于驱动大多数业务应用程序的文档自动化场景。
发票自动化
电子商务订单处理程序会在收到付款后立即生成发票 PDF 文件。 RenderHtmlAsPdf的方法,该方法使用订单数据填充的Razor模板HTML字符串,然后将结果发送到客户的电子邮件地址。 因为PDF从未触及文件系统,所以没有需要清理的残余文件,没有共享临时目录的竞争条件,也没有容器化部署的权限问题。 有关从 Razor 视图渲染 HTML 的更多信息,请参阅ASP.NET Core PDF 生成指南。
定期报告分发
使用IHostedService计划的后台服务每周一06:00生成每周分析摘要。 它查询数据库,构建 HTML 报告字符串,使用 IronPDF 渲染,并使用 MailKit 将其发送到邮件列表。整个流程以异步工作流的形式运行,因此在 SMTP 握手期间不会占用线程池线程。 对于 Azure 托管的工作负载, Azure PDF 生成器指南解释了如何在 Azure 应用服务和 Azure Functions 中部署 IronPDF。
在 ASP.NET Core 中生成收据
在 ASP.NET Core 最小 API 或控制器操作中,POST 端点接收结账有效负载,生成收据 PDF,并返回 HTTP 200,同时发送电子邮件。 将电子邮件发送逻辑保留在后台Task中,以便HTTP响应立即返回给客户端:
app.MapPost("/checkout", async (CheckoutRequest req, IEmailService emailService) =>
{
var renderer = new ChromePdfRenderer();
PdfDocument receipt = renderer.RenderHtmlAsPdf(BuildReceiptHtml(req));
// Fire and forget -- do not await so the HTTP response is immediate
_ = emailService.SendReceiptAsync(req.CustomerEmail, receipt.BinaryData);
return Results.Ok(new { message = "Order confirmed." });
});
app.MapPost("/checkout", async (CheckoutRequest req, IEmailService emailService) =>
{
var renderer = new ChromePdfRenderer();
PdfDocument receipt = renderer.RenderHtmlAsPdf(BuildReceiptHtml(req));
// Fire and forget -- do not await so the HTTP response is immediate
_ = emailService.SendReceiptAsync(req.CustomerEmail, receipt.BinaryData);
return Results.Ok(new { message = "Order confirmed." });
});
Imports System.Threading.Tasks
app.MapPost("/checkout", Async Function(req As CheckoutRequest, emailService As IEmailService) As Task(Of IResult)
Dim renderer As New ChromePdfRenderer()
Dim receipt As PdfDocument = renderer.RenderHtmlAsPdf(BuildReceiptHtml(req))
' Fire and forget -- do not await so the HTTP response is immediate
_ = emailService.SendReceiptAsync(req.CustomerEmail, receipt.BinaryData)
Return Results.Ok(New With {.message = "Order confirmed."})
End Function)
即使 SMTP 服务器速度较慢,也能将 API 响应时间保持在 100 毫秒以下。 emailService注册为一个范围或瞬态服务,该服务包装MailKit SmtpClient。
如何处理错误和重试?
网络运行失败。 SMTP 服务器暂时不可用,身份验证令牌过期,附件大小限制因提供商而异。 从一开始就在电子邮件发送流程中建立弹性。
将 MailKit 的发送逻辑封装在 try/catch 语句中,并将失败情况记录到持久队列中,以便可以重试:
using IronPdf;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using Microsoft.Extensions.Logging;
async Task SendPdfEmailWithRetryAsync(
byte[] pdfBytes,
string recipientEmail,
string subject,
ILogger logger,
int maxAttempts = 3)
{
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
try
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Mailer", "mailer@example.com"));
message.To.Add(MailboxAddress.Parse(recipientEmail));
message.Subject = subject;
var builder = new BodyBuilder { TextBody = "Your document is attached." };
builder.Attachments.Add("document.pdf", pdfBytes, new ContentType("application", "pdf"));
message.Body = builder.ToMessageBody();
using var smtpClient = new SmtpClient();
await smtpClient.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
await smtpClient.AuthenticateAsync("user", "pass");
await smtpClient.SendAsync(message);
await smtpClient.DisconnectAsync(true);
logger.LogInformation("Email sent to {Email} on attempt {Attempt}", recipientEmail, attempt);
return;
}
catch (Exception ex) when (attempt < maxAttempts)
{
logger.LogWarning(ex, "Send attempt {Attempt} failed. Retrying...", attempt);
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}
}
}
using IronPdf;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using Microsoft.Extensions.Logging;
async Task SendPdfEmailWithRetryAsync(
byte[] pdfBytes,
string recipientEmail,
string subject,
ILogger logger,
int maxAttempts = 3)
{
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
try
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Mailer", "mailer@example.com"));
message.To.Add(MailboxAddress.Parse(recipientEmail));
message.Subject = subject;
var builder = new BodyBuilder { TextBody = "Your document is attached." };
builder.Attachments.Add("document.pdf", pdfBytes, new ContentType("application", "pdf"));
message.Body = builder.ToMessageBody();
using var smtpClient = new SmtpClient();
await smtpClient.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
await smtpClient.AuthenticateAsync("user", "pass");
await smtpClient.SendAsync(message);
await smtpClient.DisconnectAsync(true);
logger.LogInformation("Email sent to {Email} on attempt {Attempt}", recipientEmail, attempt);
return;
}
catch (Exception ex) when (attempt < maxAttempts)
{
logger.LogWarning(ex, "Send attempt {Attempt} failed. Retrying...", attempt);
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}
}
}
Imports IronPdf
Imports MailKit.Net.Smtp
Imports MailKit.Security
Imports MimeKit
Imports Microsoft.Extensions.Logging
Public Async Function SendPdfEmailWithRetryAsync(
pdfBytes As Byte(),
recipientEmail As String,
subject As String,
logger As ILogger,
Optional maxAttempts As Integer = 3) As Task
For attempt As Integer = 1 To maxAttempts
Try
Dim message = New MimeMessage()
message.From.Add(New MailboxAddress("Mailer", "mailer@example.com"))
message.To.Add(MailboxAddress.Parse(recipientEmail))
message.Subject = subject
Dim builder = New BodyBuilder With {
.TextBody = "Your document is attached."
}
builder.Attachments.Add("document.pdf", pdfBytes, New ContentType("application", "pdf"))
message.Body = builder.ToMessageBody()
Using smtpClient = New SmtpClient()
Await smtpClient.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls)
Await smtpClient.AuthenticateAsync("user", "pass")
Await smtpClient.SendAsync(message)
Await smtpClient.DisconnectAsync(True)
End Using
logger.LogInformation("Email sent to {Email} on attempt {Attempt}", recipientEmail, attempt)
Return
Catch ex As Exception When attempt < maxAttempts
logger.LogWarning(ex, "Send attempt {Attempt} failed. Retrying...", attempt)
Await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)))
End Try
Next
End Function
指数退避——第一次失败后 2 秒,第二次失败后 4 秒——可防止对过载的 SMTP 服务器进行猛烈攻击。 在生产应用程序中,用消息队列(Azure 服务总线、RabbitMQ 或 AWS SQS)替换重试循环,以便故障在应用程序重启后仍然存在。
如果HTML内容无法渲染,IronPDF也会抛出PdfException。 将其与 SMTP 异常分开捕获,以便错误消息更具体:
PdfDocument pdf;
try
{
pdf = renderer.RenderHtmlAsPdf(htmlContent);
}
catch (IronPdf.Exceptions.PdfException ex)
{
logger.LogError(ex, "PDF rendering failed");
throw;
}
PdfDocument pdf;
try
{
pdf = renderer.RenderHtmlAsPdf(htmlContent);
}
catch (IronPdf.Exceptions.PdfException ex)
{
logger.LogError(ex, "PDF rendering failed");
throw;
}
Imports IronPdf.Exceptions
Dim pdf As PdfDocument
Try
pdf = renderer.RenderHtmlAsPdf(htmlContent)
Catch ex As PdfException
logger.LogError(ex, "PDF rendering failed")
Throw
End Try
将渲染错误与交付错误分开,可以加快调试速度。 为了更全面地了解自动化文档管道中的错误处理, 5 步 PDF 生成指南详细介绍了验证模式。
如何将附件大小控制在提供商限制范围内?
大多数商业电子邮件服务商都对附件大小有限制。Gmail 将单个附件的大小限制为 25 MB; Microsoft 365 标准邮箱的默认大小为 20 MB。 样式繁多的 HTML 报表,尤其是嵌入图片的报表,可能会意外地超出这些限制。
三种方法有助于控制在限度之内:
渲染前请压缩图像。内嵌图像应使用压缩的 JPEG 或 WebP 格式,而非未压缩的 PNG 格式。 一个 600 dpi 的 PNG 格式 logo 会使 PDF 文件增加几兆字节; 通常情况下,质量为 85% 的 JPEG 图片大小小于 200 KB,但视觉效果却相同。
使用IronPDF的压缩设置。 PdfDocument.CompressImages方法在渲染后降低嵌入位图的分辨率。 在读取BinaryData之前调用它:
pdf.CompressImages(60); // quality 0-100
byte[] compressedPdfBytes = pdf.BinaryData;
pdf.CompressImages(60); // quality 0-100
byte[] compressedPdfBytes = pdf.BinaryData;
pdf.CompressImages(60) ' quality 0-100
Dim compressedPdfBytes As Byte() = pdf.BinaryData
将大型报告拆分成多封邮件发送。如果报告即使经过压缩后仍然超过服务商的限制,则为每个部分生成一个 PDF 文件,并分别通过单独的邮件发送。 PDF拆分和合并指南页展示了如何使用PdfDocument。
SMTP 大小限制的外部参考: Gmail 附件限制、 Microsoft 365 邮件大小限制。
下一步计划是什么?
现在,您已经有一个可运行的模板,可以使用IronPDF在内存中生成PDF,并通过MailKit或System.Net.Mail将其作为电子邮件附件发送。 内存中的方法消除了磁盘读写,简化了容器化部署,并在无需清理临时文件的情况下扩展到高吞吐量场景。
为了深化融合:
- 阅读HTML 转 PDF 教程,掌握带有页眉、页脚和页码的复杂文档布局。
- 探索自定义 PDF 渲染选项,以控制边距、页面大小和 JavaScript 执行超时。
- 在附加文件之前,向生成的 PDF 文件添加数字签名,为收件人提供防篡改文档。
- 部署到Azure Functions 或 App Service ,实现大规模无服务器文档生成。 -免费试用 IronPDF ,在购买生产许可证之前测试其全部功能,或查看部署定价的许可选项。
常见问题解答
如何用 C# 将生成的 PDF 作为电子邮件附件发送?
使用IronPDF,您可以通过.NET的电子邮件发送功能,将生成的PDF文件作为电子邮件附件发送。
在 .NET 应用程序中通过电子邮件发送 PDF 文件有什么好处?
在 .NET 应用程序中通过电子邮件发送 PDF 文件有助于自动交付文档、简化业务工作流程并加强客户沟通。
IronPDF 能否处理 PDF 中用于电子邮件附件的动态内容?
是的,IronPDF动态生成PDF内容,使其适合于需要将定制PDF作为电子邮件附件发送的事件驱动应用程序。
IronPDF 电子邮件发送方法中常用的参数有哪些?
常见参数包括电子邮件主题、发件人信息和 EventArgs(确保在事件驱动应用程序中进行高效处理)。
为什么 IronPDF 适合自动交付文档?
IronPDF适合用于自动化文档递送,因为它提供可靠的PDF创建,并与C#的电子邮件发送功能集成。
是否可以使用 IronPDF 安排发送 PDF 电子邮件?
是的,IronPDF 可以集成到计划任务中,在指定时间自动发送 PDF 电子邮件,提高工作流程效率。
IronPDF 是否支持从各种数据源创建 PDF 文件作为电子邮件附件?
IronPDF支持从多个数据源创建PDF,允许开发者生成用于电子邮件附件的详细文档。
IronPDF 如何加强与客户的电子邮件沟通?
通过允许生成和发送详细的 PDF 文档作为附件,IronPDF 提高了与客户进行电子邮件交流的专业性和清晰度。
IronPDF可以用来发送发票和报告作为PDF附件吗?
是的,IronPDF非常适合生成和发送发票、报告及其他文档作为PDF附件,以满足各种业务需求。
IronPDF 在改进业务工作流程方面发挥什么作用?
IronPDF通过启用PDF文档的创建和分发来改进业务工作流程,减少手动干预和错误。

