푸터 콘텐츠로 바로가기
IRONPDF 사용하기

C#에서 PDF 파일을 이메일 첨부파일로 보내는 방법

문서 자동화 전송은 거의 모든 비즈니스 .NET 애플리케이션에서 나타나는 요구사항입니다. 주문이 이루어지면 몇 초 안에 인보이스가 고객에게 도달해야 합니다. 보고서가 밤새 실행되면 이해관계자들은 회사에 도착하기 전에 받은 편지함에 그것을 기대합니다. 가장 간단하고 보편적으로 지원되는 전송 형식은 이메일 첨부 파일로 전송되는 PDF입니다. 이 가이드는 메모리 내에서 IronPDF로 PDF 문서를 생성하고 MailKit 또는 내장된 System.Net.Mail 네임스페이스를 사용하여 이메일 첨부 파일로 전송하는 전체 과정에 대하여 설명하며, 디스크에 단 한 바이트도 쓰지 않습니다.

필수 패키지를 설치하는 방법은?

이 워크플로는 두 개의 패키지가 구동합니다: PDF 생성 라이브러리와 이메일 전송 라이브러리. Visual Studio의 패키지 관리자 콘솔에서 또는 .NET CLI를 통해 둘 다 설치합니다.

Install-Package IronPdf
dotnet add package IronPdf
Install-Package MailKit
dotnet add package MailKit
Install-Package IronPdf
dotnet add package IronPdf
Install-Package MailKit
dotnet add package MailKit
SHELL

IronPDF는 HTML, CSS, JavaScript를 픽셀 완벽한 PDF 문서로 변환하는 크로미엄 기반 렌더링 엔진을 제공합니다. Windows, Linux, macOS에서 작동하므로 동일한 코드가 ASP.NET Core 웹 API, 백그라운드 서비스, Azure Function에서 작동합니다. MailKit은 Microsoft가 모든 새로운 .NET 이메일 개발을 위해 권장하는 라이브러리로, SMTP, IMAP, POP3, OAuth 2.0 및 전체 MIME 구성을 지원합니다. MailKit 소스 및 문서는 GitHub에서 사용할 수 있습니다.

메모리에서 PDF 문서를 생성하는 방법은?

ChromePdfRenderer 클래스HTML을 PDF로 변환하는 입구점입니다. HTML 문자열을 RenderHtmlAsPdf에 전달하면 메모리 내에서만 존재하는 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")
$vbLabelText   $csharpLabel

RenderHtmlAsPdf 메서드는 Google Chrome을 구동하는 동일한 Chromium 엔진을 사용하여 HTML을 파싱하므로, 테이블, CSS Grid, Flexbox 및 포함된 글꼴이 브라우저에 표시되는 것과 동일하게 정확하게 렌더링됩니다. 결과는 디스크 읽기 및 쓰기가 전혀 없이 전체 PDF 바이너리를 반환하는 PdfDocumentBinaryData 속성을 갖습니다. 외부 이미지나 스타일시트를 불러오는 문서의 경우 선택적인 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
$vbLabelText   $csharpLabel

여백은 밀리미터 단위로 설정됩니다. {page}{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
$vbLabelText   $csharpLabel

builder.Attachments.Add는 수신자가 이메일 클라이언트에서 보는 파일 이름, pdf.BinaryData로부터의 원시 바이트 배열 및 application/pdf로 MIME 타입을 지정하는 ContentType 인스턴스를 세 가지 인자로 받습니다. 비동기 SMTP 메소드는 네트워크 작업이 완료되는 동안 호출 스레드를 자유롭게 유지합니다 -- 이는 여러 동시 요청을 처리하는 ASP.NET Core 컨트롤러에서 중요합니다.

SecureSocketOptions.StartTls는 587 포트에서 SMTP 서버와 암호화된 채널을 협상합니다. Gmail의 경우 계정 비밀번호 대신 앱 비밀번호를 사용하십시오. Google 계정 보안 > 앱 비밀번호에서 생성한 후 AuthenticateAsync로 전달합니다. Microsoft 365의 경우 테넌트에서 기본 인증을 비활성화한 경우 MailKit의 SaslMechanismOAuth2 클래스를 통해 OAuth 2.0 인증을 구성하십시오.

여러 수신자에게 보내기

같은 이메일에 여러 사람을 복사하려면, SendAsync를 호출하기 전에 주소를 To, Cc, 또는 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"))
$vbLabelText   $csharpLabel

단일 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);
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
$vbLabelText   $csharpLabel

MailKit과의 주요 차이점은 System.Net.Mail.Attachment가 바이트 배열을 직접 받아들이지 않는다는 것입니다. 먼저 pdf.BinaryDataMemoryStream로 감싸야 합니다. MailMessageSmtpClient는 모두 SMTP 연결을 해제하고 전송 후 기본 스트림을 플러시하는 using 문에 감싸져 있습니다. 만약 MailMessageusing를 지정하지 않으면, 특정 런타임의 경우 첨부 파일 스트림이 전송 완료 전에 해제될 수 있습니다.

MailKit과 System.Net.Mail 선택하기

MailKit 대 System.Net.Mail 기능 비교
특징 MailKit System.Net.Mail
OAuth 2.0 인증 아니요
IMAP / POP3 지원 아니요
비동기 우선 API 부분적
Microsoft 권장 권장됨 레거시
추가 NuGet 패키지 필요함 필요하지 않음
복잡한 MIME 구성 전체 지원 기본

새 프로젝트의 임의의 경우 특히 SMTP 서버가 OAuth를 요구하거나 응답을 읽기 위해 IMAP이 필요한 경우 MailKit을 선택하십시오. 코드베이스가 이미 그에 의존하고 있고 마이그레이션 비용을 정당화할 수 없는 경우에는 System.Net.Mail를 사용하십시오.

이 패턴을 실제 비즈니스 워크플로우에 적용하는 방법은 무엇입니까?

메모리 내 PDF-이메일 패턴은 대부분의 비즈니스 애플리케이션을 구동하는 문서 자동화 시나리오에 직접 적용됩니다.

송장 자동화

전자상거래 주문 관리자가 결제가 완료되자마자 송장 PDF를 즉시 생성합니다. OrderConfirmed 이벤트는 주문 데이터에서 채워진 Razor 템플릿 HTML 문자열을 포함하는 메서드를 호출하고 그 결과를 고객의 이메일 주소로 전송합니다. PDF가 파일 시스템을 절대 접하지 않기 때문에, 남은 파일을 정리할 필요가 없고, 공유 임시 디렉토리에서 경합 조건이 없으며, 컨테이너화된 배포에서 권한 문제가 없습니다. Razor 뷰에서 HTML 렌더링에 대해 더 알고 싶다면 ASP.NET Core PDF 생성 가이드를 참조하십시오.

일정 보고서 배포

IHostedService로 예약된 백그라운드 서비스는 매주 월요일 06:00에 주간 분석 요약을 생성합니다. 데이터베이스를 쿼리하고, HTML 보고서 문자열을 작성하여 IronPDF로 렌더링하고, MailKit을 사용하여 배포 목록에 보냅니다. 전체 파이프라인이 비동기 워크플로로 실행되므로 SMTP 핸드셰이크 동안 스레드 풀 스레드를 유지하지 않습니다. Azure에 호스팅된 작업의 경우 Azure PDF 생성기 가이드는 Azure App Service 및 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)
$vbLabelText   $csharpLabel

SMTP 서버가 느려도 API 응답 시간을 100ms 이하로 유지합니다. 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
$vbLabelText   $csharpLabel

지수 백오프 — 첫 번째 실패 후 2초, 두 번째 실패 후 4초 — 과부하된 SMTP 서버를 마구 두드리는 것을 방지합니다. 실제 애플리케이션에서는 애플리케이션 재시작 시에도 실패가 지속되도록 메시지 큐(Azure Service Bus, RabbitMQ, 또는 AWS SQS)로 재시도 루프를 대체하세요.

IronPDF는 HTML 콘텐츠를 렌더링할 수 없을 때 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
$vbLabelText   $csharpLabel

렌더링 오류와 전달 오류를 분리하면 디버깅 속도가 빨라집니다. 자동화된 문서 파이프라인의 오류 처리에 대한 더 넓은 시각을 얻으려면 5단계 PDF 생성 가이드에서 검증 패턴을 자세히 다룹니다.

첨부 파일 크기를 제공자 제한 아래로 어떻게 유지하나요?

대부분의 상업용 이메일 제공자는 최대 첨부 파일 크기를 강제합니다. Gmail은 개별 첨부 파일을 25MB로 제한합니다; Microsoft 365는 표준 사서함에 대해 기본적으로 20MB입니다. 이미지를 포함한 복잡한 HTML 보고서는 예상치 못하게 이러한 제한을 초과할 수 있습니다.

3가지 기술로 제한 내에 머무르게 도와줍니다:

렌더링 전에 이미지를 압축하세요. 인라인 이미지는 압축된 JPEG 또는 WebP를 사용해야 하며 비압축 PNG를 사용하지 않아야 합니다. 600 dpi PNG 로고는 PDF에 여러 메가바이트를 추가할 수 있습니다; 85% 품질의 JPEG는 시각적으로 같은 결과를 제공하면서 보통 200KB 이하입니다.

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
$vbLabelText   $csharpLabel

큰 보고서를 여러 이메일로 나눕니다. 압축 후에도 제공자 제한을 초과하는 보고서는 섹션당 하나의 PDF를 생성하고 각각을 별도의 이메일로 보냅니다. PDF 분할 및 병합 방법 페이지에서는 CopyPages를 사용하여 페이지 범위별로 PdfDocument를 나누는 방법을 보여줍니다.

SMTP 크기 제한에 대한 외부 참고 사항: Gmail 첨부 파일 제한, Microsoft 365 메시지 크기 제한.

다음 단계는 무엇입니까?

이제 IronPDF로 메모리에서 PDF를 생성하고 MailKit 또는 System.Net.Mail을 사용하여 이메일 첨부파일로 보내는 작업용 템플릿을 갖게 되었습니다. 제자리에서 읽고 쓰는 디스크를 제거하고, 컨테이너화된 배포를 간소화하며, 임시 파일 청소가 필요 없게 높이 스루풋 시나리오로 확장합니다.

통합을 심화하기 위해:

자주 묻는 질문

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 문서의 생성 및 배포를 가능하게 하여 수동 개입과 오류를 줄임으로써 비즈니스 워크플로를 개선합니다.

커티스 차우
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.

아이언 서포트 팀

저희는 주 5일, 24시간 온라인으로 운영합니다.
채팅
이메일
전화해