ฉันสามารถตั้งค่าเทมเพลต HTML / อีเมลด้วย ASP.NET ได้หรือไม่


97

ฉันกำลังทำงานกับไซต์ที่จะส่งอีเมลจำนวนมาก ฉันต้องการตั้งค่าทั้งข้อความส่วนหัวและส่วนท้ายหรือแม้กระทั่งแม่แบบเพื่อให้ผู้ใช้แก้ไขอีเมลเหล่านี้ได้อย่างง่ายดายหากต้องการ

หากฉันฝัง HTML ไว้ในตัวอักษรสตริง C # มันน่าเกลียดและพวกเขาจะต้องกังวลเกี่ยวกับการหลบหนี การรวมไฟล์แบบแบนสำหรับส่วนหัวและส่วนท้ายอาจใช้งานได้ แต่มีบางอย่างที่ไม่ถูกต้อง

อะไรจะเหมาะที่สุดในการใช้.ASPXเพจเป็นเทมเพลตจากนั้นเพียงแค่บอกโค้ดของฉันให้แสดงหน้านั้นและใช้ HTML ที่ส่งกลับมาสำหรับอีเมล

มีวิธีที่ดีและง่ายในการทำเช่นนี้หรือไม่? มีวิธีที่ดีกว่าในการแก้ปัญหานี้หรือไม่?

อัปเดต:
ฉันได้เพิ่มคำตอบที่ช่วยให้คุณสามารถใช้เพจ. aspx มาตรฐานเป็นเทมเพลตอีเมลได้ เพียงแค่แทนที่ตัวแปรทั้งหมดเช่นที่คุณทำตามปกติใช้ databinding เป็นต้นจากนั้นก็จับผลลัพธ์ของหน้าและ voila! คุณมีอีเมล HTML ของคุณ!

อัปเดตด้วย CAVEAT !!!:
ฉันใช้คลาส MailDefinition บนเพจ aspx บางเพจได้ดี แต่เมื่อพยายามใช้คลาสนี้ระหว่างกระบวนการเซิร์ฟเวอร์ที่กำลังทำงานอยู่มันล้มเหลว ฉันเชื่อว่าเป็นเพราะเมธอด MailDefinition.CreateMailMessage () ต้องการการควบคุมที่ถูกต้องในการอ้างอิงแม้ว่าจะไม่ได้ทำอะไรบางอย่างเสมอไป ด้วยเหตุนี้ฉันจึงขอแนะนำแนวทางของฉันโดยใช้เพจ aspx หรือแนวทางของ Mun โดยใช้เพจ ascx ซึ่งดูเหมือนจะดีกว่าเล็กน้อย


อีกวิธีหนึ่งคือการใช้AlphaMailเพื่อสร้างและส่งอีเมลของคุณโดยใช้ C # และภาษาเทมเพลตComlang
Timothy E. Johansson

1
@JohnBubriski: ทำงานผมแก้ไขปัญหาการควบคุมที่คุณกล่าวถึงใน "การปรับปรุงด้วยคำเตือน" ใช้เช่น:new System.Web.UI.Control() mailDefinition.CreateMailMessage("somebody@fake.com", iDictionaryReplacements, new System.Web.UI.Control())
Theophilus

ใช่ฉันได้ทำเช่นนั้นเช่นกัน แต่เนื่องจากการถือกำเนิดของ Razor นี่เป็นความคิดที่ดีน้อยลง
John Bubriski

คำตอบ:


73

มีคำตอบมากมายที่นี่แล้ว แต่ฉันไปเจอบทความดีๆเกี่ยวกับวิธีใช้ Razor กับเทมเพลตอีเมล Razor ถูกผลักด้วย ASP.NET MVC 3 แต่ MVC ไม่จำเป็นต้องใช้ Razor นี่เป็นการประมวลผลที่ค่อนข้างเนียนในการทำเทมเพลตอีเมล

ตามที่บทความระบุว่า "สิ่งที่ดีที่สุดของ Razor คือไม่เหมือนกับรุ่นก่อน ๆ (เว็บฟอร์ม) ที่ไม่ได้เชื่อมโยงกับสภาพแวดล้อมของเว็บเราสามารถโฮสต์ไว้นอกเว็บได้อย่างง่ายดายและใช้เป็นเครื่องมือแม่แบบเพื่อวัตถุประสงค์ต่างๆ"

การสร้างอีเมล HTML ด้วย RazorEngine - ตอนที่ 01 - บทนำ

การใช้ประโยชน์จากเทมเพลตมีดโกนภายนอก ASP.NET: ไม่เพียง แต่สำหรับ HTML อีกต่อไป!

เทมเพลตอีเมลที่ชาญฉลาดขึ้นใน ASP.NET ด้วย RazorEngine

คล้ายกัน Stackoverflow QA

Templating โดยใช้ RazorEngine API ใหม่

ใช้มีดโกนโดยไม่ใช้ MVC

เป็นไปได้หรือไม่ที่จะใช้ Razor View Engine นอก asp.net


1
+1 แต่โปรดระวังหากผู้ใช้ให้เทมเพลตเนื่องจากพวกเขาสามารถเรียกใช้รหัส C # จากเทมเพลตทำให้มีอำนาจในระบบของคุณมากกว่าที่คุณต้องการ
AaronLS

คุณคิดอย่างไรเกี่ยวกับความปลอดภัย การใช้โปรแกรมสร้างเทมเพลตนี้ทำให้อาจฟอร์แมตระบบไฟล์ทั้งหมด ฉันชอบเครื่องยนต์ แต่นั่นทำให้ฉันต้องดูเครื่องยนต์อื่น ๆ
der_chirurg

55

คุณอาจต้องการลองโหลดตัวควบคุมจากนั้นแสดงผลเป็นสตริงและตั้งค่าเป็นเนื้อหา HTML:

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

จากนั้นคุณสามารถสร้างอีเมลของคุณได้ตามปกติ:

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

การควบคุมผู้ใช้ของคุณอาจมีการควบคุมอื่น ๆ เช่นส่วนหัวและส่วนท้ายและยังใช้ประโยชน์จากฟังก์ชันการทำงานเช่นการผูกข้อมูล


ฉันพลาดคำตอบนี้เป็นครั้งแรก ... คล้ายกับโซลูชันของฉัน แต่มี ascx แทนที่จะเป็น aspx ฉันยังคิดว่า aspx จะดีกว่าเนื่องจากจะเสนอหน้าเว็บที่สมบูรณ์แทนที่จะเป็นตัวควบคุม แต่นั่นเป็นเพียงสิ่งที่ฉันคิด
John Bubriski

ใช่คุณสามารถใช้วิธีแก้ปัญหาอย่างใดอย่างหนึ่ง ... พวกเขาทำงานในลักษณะเดียวกัน ประโยชน์อย่างหนึ่งของแนวทางนี้คือความสม่ำเสมอ ตัวอย่างเช่นคุณสามารถแสดงข้อมูลสรุปคำสั่งซื้อให้กับผู้ใช้และรวมสิ่งที่เหมือนกันทุกประการในอีเมลยืนยันโดยใช้การควบคุมเดียวกัน
มูล

จุดรอง แต่คุณไม่มีบรรทัดในการประกาศ StringBuilder ในบล็อกโค้ดแรก
Kirschstein

9
ตัวอย่างไม่ได้อธิบายว่าโค้ดอยู่ที่ใดเป็นเพจหรือไม่เนื่องจาก LoadControl เป็นเพจ / วิธีการควบคุม
Shrage Smilowitz

@Mun คุณโหลด usercontrol ลงในตัวแปรที่เรียกว่า ctrl และคุณจะไม่อ้างอิงอีกเลยในโค้ดของคุณ มันควรจะทำงานอย่างไร?
The Muffin Man

35

คุณสามารถลองใช้คลาส MailDefinition


4
ฉันแค่อยากจะชี้ให้เห็นว่านี่เป็นสิ่งที่ดีสำหรับอีเมลพื้นฐาน แต่ไม่ใช่อะไรที่ซับซ้อน คลาส MailDefinition ไม่สนับสนุน databinding สิ่งเดียวที่ทำได้คือเสนอการเปลี่ยนสตริง แม้ว่ามันจะรวมอยู่ในตัวช่วยสร้างการสร้างบัญชีสมาชิกด้วย
John Bubriski

4
คลาส MailDefinition ต้องได้รับ Control เพื่อแสดงเนื้อหาที่เป็นเทมเพลต .. ไม่ค่อยดีนัก
Yuki

17

หากคุณต้องการส่งผ่านพารามิเตอร์เช่นชื่อผู้ใช้ชื่อผลิตภัณฑ์ ... ฯลฯ คุณสามารถใช้เอ็นจินเทมเพลตโอเพนซอร์สNVelocityเพื่อสร้างอีเมล / HTML สุดท้ายของคุณ

ตัวอย่างของ 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

การสร้างเนื้อหาอีเมลโดย MailTemplate.vm ในแอปพลิเคชันของคุณ:

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

เนื้อหาเมลผลลัพธ์คือ:

แม่แบบอีเมลตัวอย่างโดย ScarletGarden

ตัวอย่างเบื้องหน้า:

[วันที่: 12.02.2009] ชื่อ: รายการที่ 1 ค่า: 09

[วันที่: 21.02.2009] ชื่อ: รายการที่ 4 ค่า: 52

[วันที่: 01.03.2009] ชื่อ: รายการ 2 ค่า: 21

[วันที่: 23.03.2009] ชื่อ: รายการที่ 6 ค่า: 24

สำหรับการแก้ไขเทมเพลตคุณอาจใช้FCKEditorและบันทึกเทมเพลตของคุณลงในไฟล์


7

ส่วนประกอบอีเมล Mail.dllรวมถึงเอ็นจิ้นเทมเพลตอีเมล:

นี่คือภาพรวมไวยากรณ์:

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

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

</body>
</html>

และรหัสที่โหลดเทมเพลตกรอกข้อมูลจากวัตถุ c # และส่งอีเมล:

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

คุณสามารถรับข้อมูลเพิ่มเติมเกี่ยวกับบล็อกโพสต์ของเครื่องมือเทมเพลตอีเมล

หรือเพียงแค่ดาวน์โหลดส่วนประกอบอีเมล Mail.dllแล้วลองใช้งาน

โปรดทราบว่านี่เป็นผลิตภัณฑ์เชิงพาณิชย์ที่ฉันสร้างขึ้น


6

หากความยืดหยุ่นเป็นหนึ่งในข้อกำหนดเบื้องต้นของคุณ XSLT อาจเป็นตัวเลือกที่ดีซึ่งได้รับการสนับสนุนโดย. NET framework อย่างสมบูรณ์และคุณจะสามารถอนุญาตให้ผู้ใช้แก้ไขไฟล์เหล่านั้นได้ บทความนี้ ( http://www.aspfree.com/c/a/XML/XSL-Transformations-using-ASP-NET/ ) อาจเป็นประโยชน์สำหรับการเริ่มต้น (msdn มีข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้) ดังที่กล่าวโดย ScarletGarden NVelocity เป็นอีกหนึ่งทางเลือกที่ดี แต่ฉันชอบ XSLT สำหรับการสนับสนุนเฟรมเวิร์ก. NET แบบ "ในตัว" และแพลตฟอร์มที่ไม่เชื่อเรื่องพระเจ้า


ฉันไม่เคยคิดเรื่องนี้มาก่อน แต่หลังจากลองใช้วิธีอื่น ๆ มากมายฉันพบว่าวิธีนี้ใช้งานได้ดีเมื่อรวมกับการเพิ่มIXmlSerializableอินเทอร์เฟซในชั้นเรียนของฉัน เพียงไม่กี่บรรทัดฉันสามารถให้ชั้นเรียนส่งอีเมลได้
cjbarth

เอ่อฉันฝันร้ายเกี่ยวกับ XSLT อาจเป็นภาษาโปรแกรม / มาร์กอัปที่ไม่ใช้งานง่ายที่สุดที่ฉันเคยใช้งานมา และเป็นไปไม่ได้ที่จะรักษาให้ผู้อื่นและแม้แต่ตัวคุณเอง 1 เดือนหลังจากที่คุณเขียน XSLT ครั้งแรก
PussInBoots

5

ฉันคิดว่าคุณสามารถทำสิ่งนี้ได้เช่นกัน:

สร้างและหน้า. aspx และวางไว้ที่ส่วนท้ายของเมธอด OnLoad หรือเรียกด้วยตนเอง

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

ฉันไม่แน่ใจว่ามีปัญหาที่อาจเกิดขึ้นกับสิ่งนี้หรือไม่ แต่ดูเหมือนว่าจะได้ผล ด้วยวิธีนี้คุณสามารถใช้เพจ. aspx ที่มีคุณสมบัติครบถ้วนแทนคลาส MailDefinition ซึ่งรองรับเฉพาะการแทนที่ข้อความ


แม้ว่าคลาส MailDefinition จะเป็นการเริ่มต้นที่ดี แต่ก็เป็นพื้นฐานเล็กน้อย วิธีนี้ควรรองรับคุณสมบัติอื่น ๆ อีกมากมายเช่นการเชื่อมโยงฐานข้อมูลและอาจถึงขั้นติดตาม มีความคิดเห็นเกี่ยวกับเรื่องนี้หรือ gotchas ที่เป็นไปได้ไหม?
John Bubriski

เยี่ยมมาก! คุณมีปัญหากับมันหรือไม่?
John Bubriski

ดังนั้นคุณจะให้ผู้ใช้ของคุณแก้ไขไฟล์. aspx เมื่อพวกเขาต้องการเปลี่ยนแปลงเทมเพลตเมล? ฉันเรียกสิ่งนั้นว่าเป็นปัญหาที่อาจเกิดขึ้น
ไบรอัน

ฉันไม่คิดอย่างนั้นอย่างน้อยก็ไม่มีความเสี่ยงมากไปกว่าเทมเพลตอื่น ๆ ที่พวกเขาสามารถแก้ไขได้ จริงอยู่ถ้าพวกเขารู้ว่ากำลังทำอะไรอยู่พวกเขาอาจก่อให้เกิดอันตรายได้ แต่ในกรณีนี้อย่างน้อยก็ไม่น่าเป็นไปได้ มันจะไม่ใช่เพจ. aspx ที่ซับซ้อนมากกว่าเทมเพลตที่มีตัวยึดตำแหน่ง
John Bubriski

ฉันรู้มานานแล้ว แต่คุณจำวิธีแก้ปัญหาขั้นสุดท้ายได้หรือไม่? ฉันไม่สามารถใช้แนวทางเฉพาะนี้ในการทำงานกับ a Pageได้อย่างน้อยเมื่อใช้วิธีการขยายทั่วไปสำหรับการแสดงผล ดังนั้นฉันจึงเปลี่ยนไปUserControl; ดูคำตอบของฉันด้านล่าง จนถึงตอนนี้ดูเหมือนว่าจะใช้งานได้ดี ... ฉันสนใจที่จะเรียนรู้ว่าคุณทำงานอย่างไรในเวลานั้น
InteXX

4

แน่ใจว่าคุณสามารถสร้างเทมเพลต html ได้และฉันขอแนะนำเทมเพลตข้อความด้วย ในเทมเพลตคุณสามารถใส่ [BODY] ในตำแหน่งที่จะวางเนื้อหาจากนั้นคุณสามารถอ่านในเทมเพลตและแทนที่เนื้อหาด้วยเนื้อหาใหม่ คุณสามารถส่งอีเมลโดยใช้. Net Mail Class คุณเพียงแค่ต้องวนซ้ำการส่งอีเมลไปยังผู้รับทั้งหมดหลังจากที่คุณสร้างอีเมลในตอนแรก ทำงานเหมือนมีเสน่ห์สำหรับฉัน

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

คุณสามารถตัดเนื้อหา StreamReader และแทนที่ด้วย File.ReadAllText (เส้นทาง)
John Sheehan

นี่เป็นการเริ่มต้นที่ดี แต่มีฟังก์ชันสำหรับส่วนหัวและส่วนท้ายเท่านั้น นี่ไม่ได้ช่วยเรื่องร่างกายตัวเองเลยจริงๆ
John Bubriski

เนื้อหาทั้งหมดที่คุณต้องทำคือป้อนเนื้อหาเนื้อหาที่ต้องการในฟิลด์ HTMLBody และ TextBody หรือแน่นอนคุณสามารถจัดเก็บไว้ในไฟล์ได้เช่นกัน
Josh Mein

4

นี่คือหนึ่งในทางเลือกที่มากขึ้นว่าการเปลี่ยนแปลงการใช้ XSL สำหรับแม่แบบอีเมลที่ซับซ้อนมากขึ้น: การใช้งานการส่งอีเมล HTML-based จาก .NET


2
ชอบลิงค์. ขอบคุณ! สมองของฉันเริ่มหมุนและตระหนักว่าฉันสามารถก้าวไปได้อีก 1 ขั้นและมีเทมเพลต XSLT ที่ใช้วัตถุ XML Serializable หรือ WCF Data Contract ในรูปแบบอีเมล html ทันใดนั้นฉันก็มีเทมเพลตอีเมลที่ 'พิมพ์ผิด' ผ่านคลาสที่ต่อเนื่องกันได้จริง!
CodingWithSpike

2

โปรดใช้ความระมัดระวังในการทำเช่นนี้ตัวกรองสแปมดูเหมือนจะบล็อก ASP.net ที่สร้าง html ซึ่งเห็นได้ชัดว่าเป็นเพราะ ViewState ดังนั้นหากคุณจะดำเนินการนี้ตรวจสอบให้แน่ใจว่า Html ที่สร้างขึ้นนั้นสะอาด

โดยส่วนตัวฉันจะพิจารณาใช้ Asp.net MVC เพื่อให้ได้ผลลัพธ์ที่คุณต้องการ หรือNVelocityค่อนข้างดีในเรื่องนี้


1

อะไรจะเหมาะที่สุดในการใช้หน้า. ASPX เป็นเทมเพลตจากนั้นบอกรหัสของฉันให้แสดงหน้านั้นและใช้ HTML ที่ส่งคืนสำหรับอีเมล

คุณสามารถสร้าง WebRequest ได้อย่างง่ายดายเพื่อเข้าสู่หน้า ASPX และรับ HTML ที่เป็นผลลัพธ์ ด้วยการทำงานเพิ่มขึ้นเล็กน้อยคุณอาจทำได้โดยไม่ต้องใช้ WebRequest PageParser และการตอบกลับตัวกรองจะช่วยให้คุณสามารถเรียกใช้เพจและจับเอาท์พุทได้ ... แม้ว่าอาจมีวิธีที่หรูหรากว่านี้


1

ฉันมีข้อกำหนดที่คล้ายกันสำหรับ 1 ในโครงการที่คุณต้องส่งอีเมลจำนวนมากในแต่ละวันและลูกค้าต้องการการควบคุมเทมเพลต html สำหรับอีเมลประเภทต่างๆอย่างสมบูรณ์

เนื่องจากมีอีเมลจำนวนมากที่ต้องส่งประสิทธิภาพจึงเป็นปัญหาหลัก

สิ่งที่เราคิดขึ้นมาคือเนื้อหาคงที่ในเซิร์ฟเวอร์ sql ที่คุณบันทึกเทมเพลต html ทั้งหมดมาร์กอัป (พร้อมกับตัวยึดตำแหน่งเช่น [UserFirstName], [UserLastName] ซึ่งถูกแทนที่ด้วยข้อมูลจริงในขณะทำงาน) สำหรับอีเมลประเภทต่างๆ

จากนั้นเราโหลดข้อมูลนี้ในแคช asp.net - ดังนั้นเราจึงไม่อ่านเทมเพลต html ซ้ำแล้วซ้ำเล่า - แต่เมื่อมีการเปลี่ยนแปลงจริงเท่านั้น

เราให้โปรแกรมแก้ไขแบบ WYSIWYG แก่ลูกค้าเพื่อแก้ไขเทมเพลตเหล่านี้ผ่านทางเว็บฟอร์มผู้ดูแลระบบ เมื่อใดก็ตามที่มีการอัปเดตเราจะรีเซ็ตแคช asp.net

จากนั้นเราก็มีตารางแยกต่างหากสำหรับบันทึกอีเมลซึ่งอีเมลทุกฉบับที่จะส่งจะถูกบันทึกไว้ ตารางนี้มีฟิลด์ที่เรียกว่า emailType, emailSent และ numberOfTries

เราทำงานทุกๆ 5 นาทีสำหรับประเภทอีเมลที่สำคัญ (เช่นสมัครสมาชิกใหม่ลืมรหัสผ่าน) ซึ่งจะต้องส่งโดยเร็ว

เราทำงานอื่นทุก ๆ 15 นาทีสำหรับประเภทอีเมลที่สำคัญน้อยกว่า (เช่นอีเมลส่งเสริมการขายอีเมลข่าว ฯลฯ )

ด้วยวิธีนี้คุณจะไม่บล็อกเซิร์ฟเวอร์ของคุณที่ส่งอีเมลแบบไม่หยุดและคุณประมวลผลอีเมลเป็นชุด เมื่อส่งอีเมลแล้วคุณตั้งค่าฟิลด์ emailSent เป็น 1


แต่คุณจัดการคอลเลกชันอย่างไร?
Riri

1
ฉันได้ทำสิ่งนี้แล้วและได้ผลดี นอกจากนี้คุณสามารถย้อนกลับไปดูบันทึกอีเมลที่ส่งไปในอดีตได้หากรายงานเป็นของคุณ
Mark Glorie

1

โปรดทราบว่าโซลูชัน aspx และ ascx ต้องการ HttpContext ปัจจุบันดังนั้นจึงไม่สามารถใช้แบบอะซิงโครนัสได้ (เช่นในเธรด) โดยไม่ต้องทำงานมาก


1

ฉันคิดว่าคำตอบง่ายๆคือ MvcMailer เป็นแพ็คเกจ NuGet ที่ให้คุณใช้เครื่องมือดูที่คุณชื่นชอบเพื่อสร้างอีเมล ดูแพ็คเกจ NuGet ที่นี่และเอกสารโครงการ

หวังว่าจะช่วยได้!


อืมแปลกคำตอบนี้ไม่ได้รับความสนใจมากขนาดนั้น?!
PussInBoots

1

DotLiquid เป็นอีกทางเลือกหนึ่ง คุณระบุค่าจากโมเดลคลาสเป็น{{ user.name }}จากนั้นในขณะรันไทม์คุณระบุข้อมูลในคลาสนั้นและเทมเพลตที่มีมาร์กอัปและจะรวมค่าเข้ามาให้คุณ มันคล้ายกับการใช้ Razor templating engine ในหลาย ๆ ด้าน รองรับสิ่งที่ซับซ้อนมากขึ้นเช่นลูปและฟังก์ชันต่างๆเช่น ToUpper สิ่งที่ดีคือสิ่งเหล่านี้ "ปลอดภัย" ดังนั้นผู้ใช้ที่สร้างเทมเพลตจะไม่ทำให้ระบบของคุณผิดพลาดหรือเขียนโค้ดที่ไม่ปลอดภัยเหมือนที่คุณทำในมีดโกน: http://dotliquidmarkup.org/try-online


0

หากคุณสามารถอนุญาตให้ ASPNET และผู้ใช้ที่เกี่ยวข้องได้รับอนุญาตให้อ่านและเขียนไฟล์คุณสามารถใช้ไฟล์ HTML ที่มีString.Format()ตัวยึดมาตรฐาน( {0},{1:C}ฯลฯ ) เพื่อบรรลุเป้าหมายนี้

อ่านไฟล์ในรูปแบบสตริงโดยใช้คลาสจากSystem.IOเนมสเปซ เมื่อคุณมีสตริงนั้นแล้วให้ส่งผ่านเป็นอาร์กิวเมนต์แรกไปString.Format()และระบุพารามิเตอร์

เก็บสายอักขระนั้นไว้และใช้เป็นเนื้อหาของอีเมลเท่านี้ก็เสร็จเรียบร้อยแล้ว วันนี้เราทำสิ่งนี้ในไซต์ (ขนาดเล็กเป็นที่ยอมรับ) หลายสิบไซต์และไม่มีปัญหาใด ๆ

ฉันควรทราบว่าวิธีนี้จะได้ผลดีที่สุดถ้า (ก) คุณไม่ได้ส่งอีเมลครั้งละ zillions (b) คุณไม่ได้ปรับแต่งอีเมลแต่ละฉบับให้เป็นแบบส่วนตัว (มิฉะนั้นคุณจะกินสตริงเป็นจำนวนมาก) และ (c ) ไฟล์ HTML นั้นค่อนข้างเล็ก


0

ตั้งค่าข้อความอีเมล IsBodyHtml = true

ใช้วัตถุของคุณที่มีเนื้อหาอีเมลของคุณทำให้วัตถุเป็นอนุกรมและใช้ xml / xslt เพื่อสร้างเนื้อหา html

หากคุณต้องการทำ AlternateViews ให้ทำสิ่งเดียวกันกับที่ jmein ใช้เทมเพลต xslt อื่นในการสร้างเนื้อหาข้อความธรรมดาเท่านั้น

ข้อดีประการสำคัญประการหนึ่งคือหากคุณต้องการเปลี่ยนเค้าโครงของคุณทั้งหมดที่คุณต้องอัปเดตเทมเพลต xslt


0

ดูที่ SubSonic (www.subsonicproject.com) พวกเขากำลังทำสิ่งนี้เพื่อสร้างโค้ด - เทมเพลตเป็น ASPX มาตรฐานและส่งออก c # วิธีการเดียวกันนี้สามารถใช้ซ้ำได้สำหรับสถานการณ์ของคุณ


0

ฉันต้องการใช้ห้องสมุด templating เช่นTemplateMachine สิ่งนี้ช่วยให้คุณสามารถใส่เทมเพลตอีเมลของคุณพร้อมกับข้อความปกติเป็นส่วนใหญ่จากนั้นใช้กฎเพื่อแทรก / แทนที่ค่าตามความจำเป็น คล้ายกับ ERB ใน Ruby มาก สิ่งนี้ช่วยให้คุณสามารถแยกการสร้างเนื้อหาอีเมลได้โดยไม่ต้องผูกมัดคุณกับบางสิ่งเช่น ASPX เป็นต้นมากเกินไปเมื่อสร้างเนื้อหาด้วยสิ่งนี้คุณสามารถส่งอีเมลได้


0

ฉันชอบคำตอบของ Raj โปรแกรมเช่น ListManager & frameworks เช่น DNN จะทำสิ่งที่คล้ายกันและหากต้องการการแก้ไขอย่างง่ายโดยผู้ใช้ที่ไม่ใช่ทางเทคนิคเครื่องมือแก้ไขแบบ WYSIWYG เพื่อแก้ไข HTML ที่จัดเก็บใน SQL เป็นวิธีที่ง่ายและตรงไปตรงมาเป็นส่วนใหญ่และสามารถรองรับการแก้ไขส่วนหัวได้อย่างอิสระจากส่วนท้าย ฯลฯ รวมทั้งการใช้โทเค็นเพื่อแทรกค่าแบบไดนามิก

สิ่งหนึ่งที่ควรคำนึงถึงหากใช้วิธีการข้างต้น (หรืออย่างใดอย่างหนึ่งจริงๆ) คือต้องเข้มงวดและระมัดระวังเกี่ยวกับรูปแบบและแท็กประเภทที่คุณอนุญาตให้บรรณาธิการแทรกได้ หากคุณคิดว่าเบราว์เซอร์เป็นสิ่งที่จู้จี้จุกจิกเพียงแค่รอจนกว่าคุณจะเห็นว่าโปรแกรมรับส่งเมลที่แตกต่างกันแสดงสิ่งเดียวกันอย่างไร ...


0

คล้ายกับคำตอบของ Canavar แต่แทนที่จะเป็น NVelocity ฉันมักจะใช้ " StringTemplate " ซึ่งฉันจะโหลดเทมเพลตจากไฟล์กำหนดค่าหรือโหลดไฟล์ภายนอกโดยใช้ File.ReadAllText () และตั้งค่า

เป็นโปรเจ็กต์ Java แต่พอร์ต C # เป็นของแข็งและฉันได้ใช้มันในหลายโปรเจ็กต์ (ใช้สำหรับเทมเพลตอีเมลโดยใช้เทมเพลตในไฟล์ภายนอกเท่านั้น)

ทางเลือกที่ดีเสมอ


0

นี่คือวิธีง่ายๆโดยใช้คลาสWebClient :

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

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

    return htmlBody;
}

จากนั้นเรียกสิ่งนี้ว่า:

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

แน่นอน CSS ของคุณจะต้องเรียงกันเพื่อแสดงรูปแบบของหน้าเว็บในโปรแกรมรับส่งเมลส่วนใหญ่ (เช่น Outlook) หากอีเมลของคุณแสดงเนื้อหาแบบไดนามิก (เช่นชื่อลูกค้า) ฉันขอแนะนำให้ใช้ QueryStrings บนเว็บไซต์ของคุณเพื่อเติมข้อมูล (เช่นhttp://www.yourwebsite.com?CustomerName=Bob )


เรียบร้อยแม้ว่าฉันคิดว่าคำตอบอื่น ๆ ส่วนใหญ่ทำได้โดยไม่ต้องส่งคำขอทางเว็บกลับไปที่ไซต์เช่นต้องโฮสต์เนื้อหาอีเมลบนไซต์ของคุณ
Rup

@Rup เข้าใจได้ แต่จำไว้ว่าหลาย ๆ ครั้งผู้คนต้องการเห็น "เวอร์ชันเว็บ" ของอีเมลอยู่แล้ว โซลูชันนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับสถานการณ์นั้น ๆ
ROFLwTIME

0

@bardev เป็นทางออกที่ดี แต่น่าเสียดายที่มันไม่เหมาะในทุกกรณี ฉันเป็นหนึ่งในนั้น

ฉันใช้ WebForms ในเว็บไซต์ (ฉันสาบานว่าจะไม่ใช้เว็บไซต์อีกแล้ว - PITA) ใน VS 2013

ฉันลองใช้คำแนะนำของ Razor แต่การเป็นเว็บไซต์ของฉันฉันไม่ได้รับ IntelliSense ที่สำคัญทั้งหมดที่ IDE มอบให้ในโครงการ MVC ฉันชอบใช้ตัวออกแบบสำหรับเทมเพลตของฉันด้วยซึ่งเป็นจุดที่สมบูรณ์แบบสำหรับ UserControl

Nix on Razor อีกครั้ง

ดังนั้นฉันจึงใช้เฟรมเวิร์กเล็ก ๆ นี้แทน (เคล็ดลับสำหรับ @mun สำหรับ UserControl และ @imatoria สำหรับ Strong Typing) จุดปัญหาที่อาจเกิดขึ้นเพียงอย่างเดียวที่ฉันเห็นคือคุณต้องระมัดระวังเพื่อให้ชื่อไฟล์. ASCX ของคุณซิงค์กับชื่อคลาส หากคุณหลงทางคุณจะได้รับข้อผิดพลาดรันไทม์

FWIW: ในการทดสอบของฉันอย่างน้อยการเรียก RenderControl () ไม่ชอบการควบคุมหน้าดังนั้นฉันจึงใช้ UserControl

ฉันค่อนข้างมั่นใจว่าฉันได้รวมทุกอย่างไว้ที่นี่แล้ว แจ้งให้เราทราบหากฉันทิ้งบางสิ่งไว้

HTH

การใช้งาน:

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

คลาสพื้นฐาน:

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

ชั้น "โรงงาน":

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

คลาสเทมเพลต:

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

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>

ASCX ส่วนท้าย:

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

</body>
</html>

เทมเพลต 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" />

รหัสเทมเพลต 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

ผู้ช่วยเหลือ:

'
' 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

เพียงแค่โยนไลบรารีที่ฉันใช้ลงในมิกซ์: https://github.com/lukencode/FluentEmail

มันแสดงอีเมลโดยใช้RazorLightใช้สไตล์ที่คล่องแคล่วในการสร้างอีเมลและรองรับผู้ส่งหลายคนนอกกรอบ มันมาพร้อมกับวิธีการขยายสำหรับ ASP.NET DI ด้วย ใช้งานง่ายตั้งค่าน้อยพร้อมรองรับข้อความธรรมดาและ HTML

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.