Tôi có thể thiết lập HTML / Mẫu email với ASP.NET không?


97

Tôi đang làm việc trên một trang web sẽ gửi một số lượng lớn email. Tôi muốn thiết lập cả văn bản đầu trang và chân trang, hoặc thậm chí có thể là các mẫu để cho phép người dùng dễ dàng chỉnh sửa những email này nếu họ cần.

Nếu tôi nhúng HTML bên trong các ký tự chuỗi C #, điều đó thật xấu xí và họ sẽ phải lo lắng về việc thoát. Bao gồm các tệp phẳng cho đầu trang và chân trang có thể hoạt động, nhưng có điều gì đó không ổn.

Điều gì sẽ là lý tưởng nếu sử dụng một .ASPXtrang làm mẫu bằng cách nào đó, sau đó chỉ cần nói mã của tôi để phân phát trang đó và sử dụng HTML được trả về cho email.

Có cách nào hay và dễ dàng để làm điều này không? Có cách nào tốt hơn để giải quyết vấn đề này không?

Đã cập nhật:
Tôi đã thêm một câu trả lời cho phép bạn sử dụng trang .aspx chuẩn làm mẫu email. Chỉ cần thay thế tất cả các biến như bạn thường làm, sử dụng databinding, v.v. Sau đó, chỉ cần nắm bắt đầu ra của trang, và thì đấy! Bạn có email HTML của mình!

CẬP NHẬT VỚI CAVEAT !!!:
Tôi đã sử dụng lớp MailDefinition trên một số trang aspx tốt, nhưng khi cố gắng sử dụng lớp này trong quá trình máy chủ đang chạy, nó không thành công. Tôi tin rằng đó là bởi vì phương thức MailDefinition.CreateMailMessage () yêu cầu một điều khiển hợp lệ để tham chiếu, mặc dù nó không phải lúc nào cũng làm được điều gì đó. Do đó, tôi muốn giới thiệu cách tiếp cận của mình bằng cách sử dụng trang aspx hoặc cách tiếp cận của Mun bằng cách sử dụng trang ascx, có vẻ tốt hơn một chút.


Một giải pháp khác là sử dụng AlphaMail để tạo và gửi email của bạn bằng C # và ngôn ngữ mẫu Comlang .
Timothy E. Johansson

1
@JohnBubriski: Tôi làm việc xung quanh vấn đề kiểm soát bạn đề cập trong "CẬP NHẬT Trong bối cảnh" sử dụng new System.Web.UI.Control()như trong: mailDefinition.CreateMailMessage("somebody@fake.com", iDictionaryReplacements, new System.Web.UI.Control()).
Theophilus

Vâng, tôi cũng đã làm điều đó, nhưng với sự ra đời của Razor, điều này không còn là một ý tưởng hay.
John Bubriski

Câu trả lời:


73

Có rất nhiều câu trả lời đã có ở đây, nhưng tôi tình cờ thấy một bài viết tuyệt vời về cách sử dụng Razor với tạo mẫu email. Razor đã được đẩy bằng ASP.NET MVC 3, nhưng MVC không bắt buộc phải sử dụng Razor. Đây là quá trình xử lý mẫu email khá khéo léo

Như bài báo xác định, "Điều tốt nhất của Razor là không giống như người tiền nhiệm của nó (biểu mẫu web), nó không bị ràng buộc với môi trường web, chúng tôi có thể dễ dàng lưu trữ nó bên ngoài web và sử dụng nó làm công cụ mẫu cho nhiều mục đích khác nhau."

Tạo email HTML với RazorEngine - Phần 01 - Giới thiệu

Tận dụng các mẫu dao cạo bên ngoài ASP.NET: Chúng không chỉ dành cho HTML nữa!

Các mẫu email thông minh hơn trong ASP.NET với RazorEngine

Stackoverflow QA tương tự

Tạo khuôn bằng API RazorEngine mới

Sử dụng Razor không có MVC

Có thể sử dụng Razor View Engine bên ngoài asp.net không


1
+1 nhưng hãy cẩn thận nếu người dùng đang cung cấp các mẫu, vì họ có thể chạy mã C # từ mẫu, cung cấp cho họ nhiều quyền lực hơn trong hệ thống của bạn hơn bạn có thể muốn.
AaronLS

Bạn nghĩ gì về An ninh. Sử dụng công cụ tạo khuôn mẫu này giúp bạn có thể định dạng toàn bộ hệ thống tệp. Tôi thích động cơ, nhưng điều đó buộc tôi phải xem xét các động cơ khác.
der_chirurg

55

Bạn cũng có thể muốn thử tải một điều khiển, sau đó hiển thị nó thành một chuỗi và đặt nó làm HTML Body:

// Declare stringbuilder to render control to
StringBuilder sb = new StringBuilder();

// Load the control
UserControl ctrl = (UserControl) LoadControl("~/Controls/UserControl.ascx");

// Do stuff with ctrl here

// Render the control into the stringbuilder
StringWriter sw = new StringWriter(sb);
Html32TextWriter htw = new Html32TextWriter(sw);
ctrl.RenderControl(htw);

// Get full body text
string body = sb.ToString();

Sau đó, bạn có thể tạo email của mình như bình thường:

MailMessage message = new MailMessage();
message.From = new MailAddress("from@email.com", "from name");
message.Subject = "Email Subject";
message.Body = body;
message.BodyEncoding = Encoding.ASCII;
message.IsBodyHtml = true;

SmtpClient smtp = new SmtpClient("server");
smtp.Send(message);

Kiểm soát người dùng của bạn có thể chứa các điều khiển khác, chẳng hạn như đầu trang và chân trang, đồng thời cũng tận dụng các chức năng như liên kết dữ liệu.


Bằng cách nào đó, tôi đã bỏ lỡ câu trả lời này lần đầu tiên khoảng ... một câu hay. Tương tự như giải pháp của tôi, nhưng với ascx thay vì aspx. Tôi vẫn nghĩ aspx sẽ tốt hơn, vì nó sẽ cung cấp một trang hoàn chỉnh, thay vì một điều khiển, nhưng đó chỉ là những gì tôi nghĩ.
John Bubriski

Đúng, bạn có thể sử dụng một trong hai giải pháp ... Chúng hoạt động theo cùng một cách. Một lợi ích của cách tiếp cận này là tính nhất quán. Ví dụ: bạn có thể hiển thị cho người dùng một bản tóm tắt đơn đặt hàng và bao gồm chính xác điều tương tự trong email xác nhận bằng cách sử dụng lại cùng một điều khiển.
Mun

Điểm nhỏ nhưng bạn đang thiếu một dòng để khai báo một StringBuilder trong khối mã đầu tiên.
Kirschstein

9
Ví dụ này không giải thích nơi mã nằm trong, nó có phải là một trang không ?, bởi vì LoadControl là một trang / phương thức điều khiển.
Shrage Smilowitz

@Mun, Bạn tải usercontrol vào một biến có tên là ctrl và bạn sẽ không bao giờ tham chiếu lại nó trong mã của mình. Công việc này dự định làm như thế nào nhỉ?
The Muffin Man

35

Bạn có thể thử lớp MailDefinition


4
Tôi chỉ muốn chỉ ra rằng điều này là tốt cho các email cơ bản, nhưng không phải bất cứ điều gì phức tạp. Lớp MailDefinition không hỗ trợ databinding. Điều duy nhất nó thực sự làm là cung cấp các chuỗi thay thế. Mặc dù, nó cũng được tích hợp vào Trình hướng dẫn tạo tài khoản thành viên.
John Bubriski

4
Lớp MailDefinition phải có được Điều khiển để hiển thị nội dung mẫu .. Không tốt lắm.
Yuki

17

Nếu bạn muốn chuyển các tham số như tên người dùng, tên sản phẩm, ... vv, bạn có thể sử dụng công cụ mẫu mã nguồn mở NVelocity để tạo email / HTML cuối cùng của bạn.

Một ví dụ về mẫu NVelocity ( MailTemplate.vm ):

A sample email template by <b>$name</b>.
<br />

Foreach example :
<br />    
#foreach ($item in $itemList)

[Date: $item.Date] Name: $item.Name, Value: $itemValue.Value
<br /><br />

#end

Tạo nội dung thư bằng MailTemplate.vm trong ứng dụng của bạn:

VelocityContext context = new VelocityContext();
context.Put("name", "ScarletGarden");
context.Put("itemList", itemList);

StringWriter writer = new StringWriter();

Velocity.MergeTemplate("MailTemplate.vm", context, writer);

string mailBody = writer.GetStringBuilder().ToString();

Nội dung thư kết quả là:

Một mẫu email mẫu của ScarletGarden .

Ví dụ về Foreach:

[Ngày: 12.02.2009] Tên: Mặt hàng 1, Giá trị: 09

[Ngày: 21.02.2009] Tên: Mặt hàng 4, Giá trị: 52

[Ngày: 01.03.2009] Tên: Mặt hàng 2, Giá trị: 21

[Ngày: 23.03.2009] Tên: Mặt hàng 6, Giá trị: 24

Để chỉnh sửa các mẫu, có thể bạn có thể sử dụng FCKEditor và lưu các mẫu của mình vào tệp.


7

Thành phần email Mail.dll bao gồm công cụ mẫu email:

Đây là tổng quan về cú pháp:

<html>
<body>
Hi {FirstName} {LastName},

Here are your orders: 
{foreach Orders}
    Order '{Name}' sent to <strong>{Street}</strong>. 
{end}

</body>
</html>

Và mã tải mẫu, điền dữ liệu từ đối tượng c # và gửi email:

Mail.Html(Template
              .FromFile("template.txt")
              .DataFrom(_contact)
              .Render())
    .Text("This is text version of the message.")
    .From(new MailBox("alice@mail.com", "Alice"))
    .To(new MailBox("bob@mail.com", "Bob"))
    .Subject("Your order")
    .UsingNewSmtp()
    .WithCredentials("alice@mail.com", "password")
    .Server("mail.com")
    .WithSSL()
    .Send();

Bạn có thể biết thêm thông tin về bài đăng trên blog của công cụ mẫu email .

Hoặc chỉ cần tải xuống thành phần email Mail.dll và dùng thử.

Xin lưu ý rằng đây là một sản phẩm thương mại mà tôi đã tạo ra.


6

Nếu tính linh hoạt là một trong những điều kiện tiên quyết của bạn, XSLT có thể là một lựa chọn tốt, được hỗ trợ hoàn toàn bởi .NET framework và bạn thậm chí có thể cho phép người dùng chỉnh sửa các tệp đó. Bài viết này ( http://www.aspfree.com/c/a/XML/XSL-Transformations-using-ASP-NET/ ) có thể hữu ích để bắt đầu (msdn có thêm thông tin về nó). Như đã nói bởi ScarletGarden NVelocity là một lựa chọn tốt khác nhưng tôi thích XSLT hơn vì hỗ trợ khuôn khổ .NET "tích hợp sẵn" và sự bất khả tri của nền tảng.


Tôi chưa bao giờ nghĩ đến điều này trước đây, nhưng sau khi thử nhiều phương pháp khác, tôi thấy điều này hoạt động tuyệt vời khi kết hợp với việc thêm IXmlSerializablegiao diện vào các lớp của tôi. Chỉ trong vài dòng, tôi có thể yêu cầu lớp của mình gửi email.
cjbarth

Urgh, tôi đã mơ thấy ác mộng về XSLT. Có lẽ là ngôn ngữ lập trình / đánh dấu không trực quan nhất mà tôi đã làm việc. Và không thể duy trì cho người khác và thậm chí cho chính bạn 1 tháng sau khi bạn mã hóa XSLT lần đầu tiên.
PussInBoots

5

Tôi nghĩ bạn cũng có thể làm điều gì đó như thế này:

Tạo và trang .aspx và đặt nó ở cuối phương thức OnLoad hoặc gọi nó theo cách thủ công.

    StringBuilder sb = new StringBuilder();
    StringWriter sw = new StringWriter(sb);
    HtmlTextWriter htmlTW = new HtmlTextWriter(sw);
    this.Render(htmlTW);

Tôi không chắc liệu có bất kỳ vấn đề tiềm ẩn nào với điều này hay không, nhưng có vẻ như nó sẽ hoạt động. Bằng cách này, bạn có thể sử dụng trang .aspx đầy đủ tính năng, thay vì lớp MailDefinition chỉ hỗ trợ thay thế Văn bản.


Mặc dù lớp MailDefinition là một khởi đầu tốt, nhưng nó hơi thô sơ. Phương pháp này sẽ hỗ trợ nhiều tính năng hơn như databinding và thậm chí có thể truy tìm. Bất kỳ suy nghĩ về điều này, hoặc có tiềm năng?
John Bubriski

Tuyệt quá! Bạn có bất kỳ vấn đề với nó?
John Bubriski

Vì vậy, bạn sẽ cho phép người dùng của mình chỉnh sửa tệp .aspx khi họ cần thay đổi mẫu thư? Tôi gọi đó là một vấn đề tiềm ẩn.
Bryan

Tôi sẽ không nghĩ như vậy, ít nhất, không có nhiều rủi ro hơn các mẫu khác mà họ có thể chỉnh sửa. Đúng là, nếu họ biết những gì họ đang làm, họ có thể gây hại, nhưng ít nhất trong trường hợp này, điều đó khó xảy ra. Nó sẽ không phải là một trang .aspx phức tạp, nhiều hơn một mẫu với trình giữ chỗ.
John Bubriski

Tôi biết đã lâu rồi, nhưng bạn có nhớ lại giải pháp cuối cùng của mình không? Tôi không thể làm cho cách tiếp cận cụ thể này hoạt động với một Page, ít nhất là khi sử dụng một phương pháp mở rộng chung cho kết xuất. Vì vậy, tôi đã chuyển sang UserControl; xem câu trả lời của tôi dưới đây. Cho đến nay, nó dường như đang hoạt động tốt ... Tôi muốn tìm hiểu cách bạn đã giải quyết nó vào thời điểm đó.
InteXX

4

Chắc chắn bạn có thể tạo một mẫu html và tôi cũng muốn giới thiệu một mẫu văn bản. Trong mẫu, bạn có thể chỉ cần đặt [BODY] vào vị trí mà nội dung sẽ được đặt và sau đó bạn có thể đọc trong mẫu và thay thế nội dung bằng nội dung mới. Bạn có thể gửi email bằng .Nets Mail Class. Bạn chỉ cần lặp lại việc gửi email đến tất cả người nhận sau khi bạn tạo email ban đầu. Làm việc như một cái duyên đối với tôi.

using System.Net.Mail;

// Email content
string HTMLTemplatePath = @"path";
string TextTemplatePath = @"path";
string HTMLBody = "";
string TextBody = "";

HTMLBody = File.ReadAllText(HTMLTemplatePath);
TextBody = File.ReadAllText(TextTemplatePath);

HTMLBody = HTMLBody.Replace(["[BODY]", content);
TextBody = HTMLBody.Replace(["[BODY]", content);

// Create email code
MailMessage m = new MailMessage();

m.From = new MailAddress("address@gmail.com", "display name");
m.To.Add("address@gmail.com");
m.Subject = "subject";

AlternateView plain = AlternateView.CreateAlternateViewFromString(_EmailBody + text, new System.Net.Mime.ContentType("text/plain"));
AlternateView html = AlternateView.CreateAlternateViewFromString(_EmailBody + body, new System.Net.Mime.ContentType("text/html"));
mail.AlternateViews.Add(plain);
mail.AlternateViews.Add(html);

SmtpClient smtp = new SmtpClient("server");
smtp.Send(m);

Bạn có thể cắt ra những thứ StreamReader và thay thế bằng File.ReadAllText (đường dẫn)
John Sheehan

Đây là một khởi đầu tốt, nhưng chỉ cung cấp chức năng cho đầu trang và chân trang. Điều này không thực sự giúp ích cho cơ thể.
John Bubriski

Cơ thể tất cả các bạn phải làm là nhập nội dung cơ thể mà là mong muốn vào HTMLBody và TextBody Fields hoặc bạn có thể tất nhiên lưu trữ chúng trong các tập tin cũng
Josh Mein

4

Đây là một giải pháp thay thế khác sử dụng biến đổi XSL cho các mẫu email phức tạp hơn: Gửi email dựa trên HTML từ các ứng dụng .NET .


2
Giống như liên kết. Cảm ơn! Bộ não của tôi bắt đầu quay và nhận ra rằng tôi có thể tiến thêm một bước nữa và có một mẫu XSLT đưa một đối tượng XML Serializable hoặc Hợp đồng dữ liệu WCF sang định dạng html-email. Đột nhiên, tôi có các mẫu email 'kiểu mạnh' thông qua các lớp thực tế có thể tuần tự hóa!
CodingWithSpike

2

Hãy cẩn thận khi thực hiện việc này, các bộ lọc SPAM dường như chặn html do ASP.net tạo, dường như là do ViewState, vì vậy nếu bạn định làm điều này, hãy đảm bảo Html được tạo ra là sạch.

Cá nhân tôi sẽ xem xét sử dụng Asp.net MVC để đạt được kết quả mong muốn của bạn. hoặc NVelocity khá giỏi trong việc này


1

Điều lý tưởng sẽ là sử dụng trang .ASPX làm mẫu bằng cách nào đó, sau đó chỉ cần nói mã của tôi để phân phát trang đó và sử dụng HTML được trả về cho email.

Bạn có thể dễ dàng chỉ cần tạo một WebRequest để truy cập một trang ASPX và nhận được HTML kết quả. Với một chút công việc nữa, bạn có thể hoàn thành công việc mà không cần WebRequest. PageParser và Response.Filter sẽ cho phép bạn chạy trang và ghi lại kết quả đầu ra ... mặc dù có thể có một số cách đơn giản hơn.


1

Tôi đã có một yêu cầu tương tự đối với một trong những dự án mà bạn phải gửi một số lượng lớn email mỗi ngày và khách hàng muốn kiểm soát hoàn toàn các mẫu html cho các loại email khác nhau.

do số lượng lớn email được gửi, hiệu suất là mối quan tâm chính.

những gì chúng tôi đưa ra là nội dung tĩnh trong máy chủ sql nơi bạn lưu toàn bộ đánh dấu mẫu html (cùng với các trình giữ chỗ, như [UserFirstName], [UserLastName] được thay thế bằng dữ liệu thực tại thời điểm chạy) cho các loại email khác nhau

sau đó chúng tôi tải dữ liệu này vào bộ nhớ cache của asp.net - vì vậy chúng tôi không đọc đi đọc lại các mẫu html - mà chỉ khi chúng thực sự được thay đổi

chúng tôi đã cung cấp cho khách hàng một trình soạn thảo WYSIWYG để sửa đổi các mẫu này thông qua biểu mẫu web quản trị. bất cứ khi nào cập nhật được thực hiện, chúng tôi đặt lại bộ nhớ cache asp.net.

và sau đó chúng tôi có một bảng riêng biệt cho nhật ký email - nơi mọi email được gửi đều được ghi lại. bảng này có các trường được gọi là emailType, emailSent và numberOfTries.

chúng tôi chỉ thực hiện một công việc cứ sau 5 phút đối với các loại email quan trọng (như đăng ký thành viên mới, quên mật khẩu) cần được gửi càng sớm càng tốt

chúng tôi thực hiện một công việc khác sau mỗi 15 phút cho các loại email ít quan trọng hơn (như email quảng cáo, email tin tức, v.v.)

Bằng cách này, bạn không chặn máy chủ của mình gửi email liên tục và bạn xử lý hàng loạt thư. khi email được gửi đi, bạn đặt trường emailSent thành 1.


Nhưng bạn đã xử lý các bộ sưu tập như thế nào?
Riri,

1
Tôi cũng đã làm điều này và nó hoạt động tốt. Ngoài ra, bạn có thể quay lại lịch sử và xem hồ sơ của các email đã gửi, nếu báo cáo là của bạn.
Mark Glorie

1

Lưu ý rằng các giải pháp aspx và ascx yêu cầu một HttpContext hiện tại, do đó, không thể được sử dụng không đồng bộ (ví dụ: trong các luồng) mà không cần nhiều công việc.


1

Tôi nghĩ câu trả lời dễ dàng là MvcMailer. Đây là gói NuGet cho phép bạn sử dụng công cụ xem yêu thích của mình để tạo email. Xem gói NuGet tại đâytài liệu dự án

Hy vọng nó giúp!


Hmm, kỳ lạ là câu trả lời này không được chú ý nhiều đến vậy ?!
PussInBoots

1

DotLiquid là một lựa chọn khác. Bạn chỉ định các giá trị từ một mô hình lớp {{ user.name }}và sau đó trong thời gian chạy, bạn cung cấp dữ liệu trong lớp đó và mẫu có đánh dấu và nó sẽ hợp nhất các giá trị vào cho bạn. Nó tương tự như việc sử dụng Razor templating engine theo nhiều cách. Nó hỗ trợ những thứ phức tạp hơn như vòng lặp và các chức năng khác nhau như ToUpper. Điều tốt đẹp là chúng "an toàn" để người dùng tạo mẫu không thể làm hỏng hệ thống của bạn hoặc viết mã không an toàn như bạn làm trong dao cạo: http://dotliquidmarkup.org/try-online


0

Nếu bạn có thể cho phép người dùng ASPNET và đi kèm cho phép đọc và ghi một tập tin, bạn có thể dễ dàng sử dụng một tập tin HTML với tiêu chuẩn String.Format()placeholders ( {0}, {1:C}, vv) để thực hiện điều này.

Chỉ đọc trong tệp, dưới dạng chuỗi, sử dụng các lớp từ System.IOkhông gian tên. Khi bạn có chuỗi đó, hãy chuyển nó làm đối số đầu tiên String.Format()và cung cấp các tham số.

Giữ chuỗi đó xung quanh và sử dụng nó làm phần nội dung của e-mail, và về cơ bản bạn đã hoàn tất. Chúng tôi thực hiện việc này trên hàng chục trang web (phải thừa nhận là nhỏ) ngày nay và không có vấn đề gì.

Tôi nên lưu ý rằng điều này hoạt động tốt nhất nếu (a) bạn không gửi hàng loạt e-mail tại một thời điểm, (b) bạn không cá nhân hóa từng e-mail (nếu không, bạn sẽ tiêu tốn rất nhiều chuỗi) và (c ) bản thân tệp HTML tương đối nhỏ.


0

Đặt thiết lập Tin nhắn Email IsBodyHtml = true

Lấy đối tượng chứa nội dung email của bạn Sắp xếp thứ tự đối tượng và sử dụng xml / xslt để tạo nội dung html.

Nếu bạn muốn làm AlternateViews, hãy làm điều tương tự mà jmein chỉ sử dụng một mẫu xslt khác để tạo nội dung văn bản thuần túy.

một trong những lợi thế chính của việc này là nếu bạn muốn thay đổi bố cục của mình, tất cả những gì bạn phải làm là cập nhật mẫu xslt.


0

Nhìn vào SubSonic (www.subsonicproject.com). Họ đang thực hiện chính xác điều này để tạo mã - mẫu là ASPX tiêu chuẩn và nó xuất ra c #. Phương pháp tương tự sẽ được sử dụng lại cho kịch bản của bạn.


0

Tôi sẽ sử dụng một thư viện tạo khuôn mẫu như TemplateMachine . điều này cho phép bạn chủ yếu đặt mẫu email của mình cùng với văn bản bình thường và sau đó sử dụng các quy tắc để chèn / thay thế các giá trị khi cần thiết. Rất giống với ERB trong Ruby. Điều này cho phép bạn tách biệt việc tạo ra nội dung thư mà không cần ràng buộc bạn quá nhiều vào thứ gì đó như ASPX, v.v. sau đó khi nội dung được tạo bằng cách này, bạn có thể gửi email đi.


0

Tôi thích câu trả lời của Raj. Các chương trình như ListManager & framework như DNN làm những việc tương tự và nếu người dùng không am hiểu kỹ thuật cần chỉnh sửa dễ dàng, thì các trình chỉnh sửa WYSIWYG để sửa đổi HTML được lưu trữ trong SQL là một cách dễ dàng, đơn giản và có thể dễ dàng điều chỉnh tiêu đề chỉnh sửa độc lập với chân trang, v.v., cũng như sử dụng mã thông báo để chèn động các giá trị.

Một điều cần lưu ý nếu sử dụng phương pháp trên (hoặc bất kỳ, thực sự) là phải nghiêm ngặt và cẩn thận về loại kiểu dáng và thẻ mà bạn cho phép người chỉnh sửa chèn. Nếu bạn cho rằng các trình duyệt quá phức tạp, chỉ cần đợi cho đến khi bạn thấy các ứng dụng email khác nhau hiển thị cùng một thứ như thế nào ...


0

Tương tự như câu trả lời của Canavar, nhưng thay vì NVelocity, tôi luôn sử dụng " StringTemplate " mà tôi tải mẫu từ tệp cấu hình hoặc tải tệp bên ngoài bằng File.ReadAllText () và đặt các giá trị.

Đó là một dự án Java nhưng cổng C # rất chắc chắn và tôi đã sử dụng nó trong một số dự án (chỉ sử dụng nó để tạo khuôn mẫu email bằng cách sử dụng mẫu trong tệp bên ngoài).

Các lựa chọn thay thế luôn tốt.


0

Đây là một cách đơn giản bằng cách sử dụng lớp WebClient :

public static string GetHTMLBody(string url)
{
    string htmlBody;

    using (WebClient client = new WebClient ())
    {
        htmlBody = client.DownloadString(url);
    }

    return htmlBody;
}

Sau đó, chỉ cần gọi nó như thế này:

string url = "http://www.yourwebsite.com";
message.Body = GetHTMLBody(url);

Tất nhiên, CSS của bạn sẽ cần phải được xếp hàng để hiển thị các kiểu của trang web trong hầu hết các ứng dụng email (chẳng hạn như Outlook). Nếu e-mail của bạn hiển thị nội dung động (ví dụ: Tên khách hàng), thì tôi khuyên bạn nên sử dụng QueryStrings trên trang web của mình để điền dữ liệu. (ví dụ : http://www.yourwebsite.com?CustomerName=Bob )


Gọn gàng, mặc dù tôi nghĩ rằng hầu hết các câu trả lời khác thực hiện điều này mà không cần thực hiện yêu cầu web quay lại trang web, tức là phải lưu trữ nội dung email trên trang web của bạn.
Rup 19/10/12

@Rup Có thể hiểu được, nhưng hãy nhớ rằng rất nhiều lần mọi người muốn xem "Phiên bản Web" của e-mail. Giải pháp này hoạt động hoàn hảo cho kịch bản đó.
ROFLwTIME

0

@bardev cung cấp một giải pháp tốt, nhưng không may là nó không lý tưởng trong mọi trường hợp. Của tôi là một trong số họ.

Tôi đang sử dụng WebForms trong một Trang web (Tôi thề rằng tôi sẽ không bao giờ sử dụng một Trang web nữa - PITA là gì) trong VS 2013.

Tôi đã thử gợi ý Razor, nhưng là một Trang web, tôi không nhận được IntelliSense quan trọng mà IDE cung cấp trong một dự án MVC. Tôi cũng thích sử dụng trình thiết kế cho các mẫu của mình - một điểm hoàn hảo cho UserControl.

Nix trên Razor một lần nữa.

Vì vậy, tôi đã nghĩ ra khung công tác nhỏ này để thay thế (mẹo dành cho @mun cho UserControl và @imatoria cho Strong Typing). Chỉ về điểm rắc rối tiềm ẩn duy nhất mà tôi có thể thấy là bạn phải cẩn thận để giữ cho tên tệp .ASCX của mình đồng bộ với tên lớp của nó. Nếu bạn đi lạc, bạn sẽ gặp lỗi thời gian chạy.

FWIW: Trong thử nghiệm của tôi, ít nhất lệnh gọi RenderControl () không giống như một điều khiển Trang, vì vậy tôi đã sử dụng UserControl.

Tôi khá chắc rằng tôi đã đưa mọi thứ vào đây; cho tôi biết nếu tôi bỏ sót điều gì đó.

HTH

Sử dụng:

Partial Class Purchase
  Inherits UserControl

  Private Sub SendReceipt()
    Dim oTemplate As MailTemplates.PurchaseReceipt

    oTemplate = MailTemplates.Templates.PurchaseReceipt(Me)
    oTemplate.Name = "James Bond"
    oTemplate.OrderTotal = 3500000
    oTemplate.OrderDescription = "Q-Stuff"
    oTemplate.InjectCss("PurchaseReceipt")

    Utils.SendMail("{0} <james.bond@mi6.co.uk>".ToFormat(oTemplate.Name), "Purchase Receipt", oTemplate.ToHtml)
  End Sub
End Class

Lớp cơ sở:

Namespace MailTemplates
  Public MustInherit Class BaseTemplate
    Inherits UserControl

    Public Shared Function GetTemplate(Caller As TemplateControl, Template As Type) As BaseTemplate
      Return Caller.LoadControl("~/MailTemplates/{0}.ascx".ToFormat(Template.Name))
    End Function



    Public Sub InjectCss(FileName As String)
      If Me.Styler IsNot Nothing Then
        Me.Styler.Controls.Add(New Controls.Styler(FileName))
      End If
    End Sub



    Private ReadOnly Property Styler As PlaceHolder
      Get
        If _Styler Is Nothing Then
          _Styler = Me.FindNestedControl(GetType(PlaceHolder))
        End If

        Return _Styler
      End Get
    End Property
    Private _Styler As PlaceHolder
  End Class
End Namespace

Lớp "Nhà máy":

Namespace MailTemplates
  Public Class Templates
    Public Shared ReadOnly Property PurchaseReceipt(Caller As TemplateControl) As PurchaseReceipt
      Get
        Return BaseTemplate.GetTemplate(Caller, GetType(PurchaseReceipt))
      End Get
    End Property
  End Class
End Namespace

Lớp Mẫu:

Namespace MailTemplates
  Public MustInherit Class PurchaseReceipt
    Inherits BaseTemplate

    Public MustOverride WriteOnly Property Name As String
    Public MustOverride WriteOnly Property OrderTotal As Decimal
    Public MustOverride WriteOnly Property OrderDescription As String
  End Class
End Namespace

Tiêu đề ASCX:

<%@ Control Language="VB" ClassName="_Header" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!--
  See https://www.campaignmonitor.com/blog/post/3317/ for discussion of DocType in HTML Email
-->

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
  <asp:PlaceHolder ID="plcStyler" runat="server"></asp:PlaceHolder>
</head>
<body>

Chân trang ASCX:

<%@ Control Language="VB" ClassName="_Footer" %>

</body>
</html>

Mẫu ASCX:

<%@ Control Language="VB" AutoEventWireup="false" CodeFile="PurchaseReceipt.ascx.vb" Inherits="PurchaseReceipt" %>

<%@ Register Src="_Header.ascx" TagName="Header" TagPrefix="uc" %>
<%@ Register Src="_Footer.ascx" TagName="Footer" TagPrefix="uc" %>

<uc:Header ID="ctlHeader" runat="server" />

  <p>Name: <asp:Label ID="lblName" runat="server"></asp:Label></p>
  <p>Order Total: <asp:Label ID="lblOrderTotal" runat="server"></asp:Label></p>
  <p>Order Description: <asp:Label ID="lblOrderDescription" runat="server"></asp:Label></p>

<uc:Footer ID="ctlFooter" runat="server" />

Mã mẫu ASCX

Partial Class PurchaseReceipt
  Inherits MailTemplates.PurchaseReceipt

  Public Overrides WriteOnly Property Name As String
    Set(Value As String)
      lblName.Text = Value
    End Set
  End Property



  Public Overrides WriteOnly Property OrderTotal As Decimal
    Set(Value As Boolean)
      lblOrderTotal.Text = Value
    End Set
  End Property



  Public Overrides WriteOnly Property OrderDescription As Decimal
    Set(Value As Boolean)
      lblOrderDescription.Text = Value
    End Set
  End Property
End Class

Người trợ giúp:

'
' FindNestedControl helpers based on tip by @andleer
' at http://stackoverflow.com/questions/619449/
'

Public Module Helpers
  <Extension>
  Public Function AllControls(Control As Control) As List(Of Control)
    Return Control.Controls.Flatten
  End Function



  <Extension>
  Public Function FindNestedControl(Control As Control, Id As String) As Control
    Return Control.Controls.Flatten(Function(C) C.ID = Id).SingleOrDefault
  End Function



  <Extension>
  Public Function FindNestedControl(Control As Control, Type As Type) As Control
    Return Control.Controls.Flatten(Function(C) C.GetType = Type).SingleOrDefault
  End Function



  <Extension>
  Public Function Flatten(Controls As ControlCollection) As List(Of Control)
    Flatten = New List(Of Control)

    Controls.Traverse(Sub(Control) Flatten.Add(Control))
  End Function


  <Extension>
  Public Function Flatten(Controls As ControlCollection, Predicate As Func(Of Control, Boolean)) As List(Of Control)
    Flatten = New List(Of Control)

    Controls.Traverse(Sub(Control)
                        If Predicate(Control) Then
                          Flatten.Add(Control)
                        End If
                      End Sub)
  End Function



  <Extension>
  Public Sub Traverse(Controls As ControlCollection, Action As Action(Of Control))
    Controls.Cast(Of Control).ToList.ForEach(Sub(Control As Control)
                                               Action(Control)

                                               If Control.HasControls Then
                                                 Control.Controls.Traverse(Action)
                                               End If
                                             End Sub)
  End Sub



  <Extension()>
  Public Function ToFormat(Template As String, ParamArray Values As Object()) As String
    Return String.Format(Template, Values)
  End Function



  <Extension()>
  Public Function ToHtml(Control As Control) As String
    Dim oSb As StringBuilder

    oSb = New StringBuilder

    Using oSw As New StringWriter(oSb)
      Using oTw As New HtmlTextWriter(oSw)
        Control.RenderControl(oTw)
        Return oSb.ToString
      End Using
    End Using
  End Function
End Module



Namespace Controls
  Public Class Styler
    Inherits LiteralControl

    Public Sub New(FileName As String)
      Dim _
        sFileName,
        sFilePath As String

      sFileName = Path.GetFileNameWithoutExtension(FileName)
      sFilePath = HttpContext.Current.Server.MapPath("~/Styles/{0}.css".ToFormat(sFileName))

      If File.Exists(sFilePath) Then
        Me.Text = "{0}<style type=""text/css"">{0}{1}</style>{0}".ToFormat(vbCrLf, File.ReadAllText(sFilePath))
      Else
        Me.Text = String.Empty
      End If
    End Sub
  End Class
End Namespace



Public Class Utils
  Public Shared Sub SendMail(Recipient As MailAddress, Subject As String, HtmlBody As String)
    Using oMessage As New MailMessage
      oMessage.To.Add(Recipient)
      oMessage.IsBodyHtml = True
      oMessage.Subject = Subject.Trim
      oMessage.Body = HtmlBody.Trim

      Using oClient As New SmtpClient
        oClient.Send(oMessage)
      End Using
    End Using
  End Sub
End Class

0

Chỉ cần ném thư viện tôi đang sử dụng vào hỗn hợp: https://github.com/lukencode/FluentEmail

Nó kết xuất email bằng RazorLight , sử dụng phong cách thông thạo để tạo email và hỗ trợ nhiều người gửi. Nó cũng đi kèm với các phương thức mở rộng cho ASP.NET DI. Sử dụng đơn giản, ít thiết lập, với văn bản thuần túy và hỗ trợ HTML.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.