IRONSOFTWAREHOME
使用IRONPDF

如何建立 .NET HTML 轉 PDF 轉換器

Curtis Chau
Curtis Chau
Updated: 2026年7月5日

自動化文件傳遞是在幾乎每個業務線的.NET應用程式中出現的需求。 當訂單下達時,發票必須在幾秒鐘內到達客戶手中。 當報告在夜間運行時,持份人期望它能在他們到達辦公室前出現在收件箱中。最簡單的、最廣泛支持的傳遞格式是作為電子郵件附件發送的PDF。 本指南將引導您完成使用C#的完整工作流程——在記憶體中使用IronPDF生成PDF文件,然後使用MailKit或內建的System.Net.Mail命名空間將其作為電子郵件附件發送,而不寫入單一字節至磁碟。

如何安裝所需的程式包?

這個工作流程由兩個程式包推動:PDF生成庫和電子郵件發送庫。 通過Visual Studio中的套件管理器控制台或.NET CLI安裝兩者。

PM > Install-Package IronPdf, MailKit

IronPDF帶來了一個基於Chromium的渲染引擎,將HTML、CSS和JavaScript轉換為像素完美的PDF文件。 它可以在Windows、Linux和macOS上運行,這意味著相同的程式碼可以在ASP.NET Core網頁API、背景服務或Azure函式中運行。 MailKit是Microsoft推薦用於所有新.NET電子郵件開發的庫——它支持SMTP、IMAP、POP3、OAuth 2.0以及完整的MIME構造。 MailKit的源程式碼和文件可在GitHub上獲得。

如何在記憶體中生成PDF文件?

ChromePdfRendererHTML到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");

RenderHtmlAsPdf方法使用Google 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;

邊距單位為毫米。 {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);

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"));

一個SendAsync調用將消息傳遞給所有地址。 MailKit在一次SMTP會話中批次執行RCPT TO命令,因此多個收件人不會影響性能。

如何使用System.Net.Mail作為替代方案?

對於針對舊的.NET版本的專案或不允許增加第三方NuGet包的專案,內建的System.Net.Mail命名空間可以進行基本的SMTP傳遞。 Microsoft不再建議將其用於新開發,但它可以覆蓋常見的使用情境而無需額外依賴。

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);

與MailKit相比的關鍵區別在於using語句中,這會在發送後處置SMTP連接並刷新底層流。 如果您省略MailMessage上的調用,附件流可能會在某些運行時完成發送前被處置。

在MailKit和System.Net.Mail之間選擇

MailKit與System.Net.Mail功能比較
功能MailKitSystem.Net.Mail
OAuth 2.0身份驗證
IMAP / POP3支持
優先非同步的API部分
Microsoft的推薦推薦傳統
附加的NuGet包需要不需要
複雜的MIME構造完全支持基本

對於任何新專案,尤其是如果SMTP伺服器需要OAuth或您需要IMAP以讀取回覆時,選擇MailKit。 當程式碼庫已經依賴於System.Net.Mail而轉移成本不合理時使用。

如何將此模式應用於實際的業務工作流程?

這種記憶體中PDF到電子郵件的模式可以直接應用於驅動大多數業務應用的文件自動化場景。

發票自動化

一個電商訂單處理器在付款捕獲後立即生成發票PDF。 RenderHtmlAsPdf,然後將結果發送到客戶的電子郵件地址。 由於PDF從未觸及文件系統,因此無需清理遺留文件,對共享臨時目錄的競賽條件也不會存在,容器化部署中也不會有許可權問題。 關於從Razor視圖渲染HTML的更多資訊,請參閱ASP.NET Core PDF生成指南

計劃報告分發

一個使用IHostedService進行計劃的背景服務每週一早上06:00生成每週分析摘要。 它查詢資料庫,構建HTML報告字串,用IronPDF渲染,並使用MailKit發送到分發列表。整個管道作為非同步工作流程運行,因此在SMTP握手期間不會佔用執行緒池執行緒。 對於以Azure為主機的工作負載,Azure PDF生成器指南解釋了如何在Azure應用服務和Azure函式內部署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." });
});

即使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)));
        }
    }
}

指數回退——第一次失敗後2秒,第二次後4秒——防止打擊過載的SMTP伺服器。 在生產應用中,將重試迴圈替換為消息隊列(Azure Service Bus,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;
}

將渲染錯誤與傳遞錯誤分開,使故障排除過程更快。 5步PDF生成指南涵蓋了自動文件流水線中錯誤處理解決方案的詳細內容。

如何保持附件在提供者限制範圍內?

大多數商業電子郵件提供商強制執行最大附件大小限制。Gmail將個別附件限制為25 MB; Microsoft 365的標準信箱預設限制為20 MB。 樣式繁重的HTML報告中包含的嵌入圖像可以意外超出這些限制。

三種技術可以幫助保持在限制內:

**在渲染前壓縮圖像。**內嵌圖像應使用壓縮的JPEG或WebP而非未壓縮的PNG。 一個600 dpi的PNG標誌可以為PDF增加好幾MB的大小; 使用85%品質的JPEG通常在200 KB以下,並且視覺效果相同。

使用IronPDF的壓縮設置。PdfDocument.CompressImages方法在渲染后減少嵌入位圖的解析度。 在讀取BinaryData之前調用它:

pdf.CompressImages(60); // quality 0-100
byte[] compressedPdfBytes = pdf.BinaryData;

**將大型報告拆分為多封電子郵件。**如果報告在壓縮後仍超出提供者限制,則生成分段的PDF,並分別以多封電子郵件形式發送。 PDF拆分和合併使用指南展示了如何使用PdfDocument

SMTP大小限制的外部參考:Gmail附件限制, Microsoft 365郵件大小限制

您的下一步該怎麼做?

您現在擁有一個工作模板來利用IronPDF在記憶體中生成PDF並使用MailKit或System.Net.Mail將其作為電子郵件附件發送。 這種記憶體中方法消除了磁碟讀寫,簡化了容器化部署,並且在不需要清理臨時文件的情況下擴展到高吞吐量場景。

要深入整合:

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

...
閱讀更多

相關文章

Key in blue circle

立即免費取得 30 天試用金鑰

無任何限制。100% 解鎖。無需信用卡。

bullet_checked無需信用卡或建立帳號無任何限制。100% 解鎖。無需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
預訂您的免費現場演示
Booking Badge

受到全球數百萬工程師的信任

Iron Software的客戶標誌
獲取您的無義務諮詢
填寫以下表格或電子郵件sales@ironsoftware.com
您的詳細資訊將始終保密
受到全球數百萬工程師的信任
Iron Software的客戶標誌
立即獲取您的30天試用金鑰
無需信用卡或帳戶建立