Posso impostare modelli HTML / e-mail con ASP.NET?


97

Sto lavorando a un sito che invierà un numero significativo di email. Voglio impostare sia il testo dell'intestazione che del piè di pagina, o forse anche dei modelli per consentire agli utenti di modificare facilmente queste e-mail se necessario.

Se incorporo l'HTML all'interno di stringhe letterali C #, è brutto e dovrebbero preoccuparsi di sfuggire. L'inclusione di file flat per l'intestazione e il piè di pagina potrebbe funzionare, ma qualcosa al riguardo non sembra giusto.

L'ideale sarebbe utilizzare una .ASPXpagina come modello in qualche modo, quindi dire al mio codice di servire quella pagina e utilizzare l'HTML restituito per l'email.

C'è un modo semplice e piacevole per farlo? C'è un modo migliore per risolvere questo problema?

Aggiornato:
ho aggiunto una risposta che consente di utilizzare una pagina .aspx standard come modello di posta elettronica. Sostituisci semplicemente tutte le variabili come faresti normalmente, usa l'associazione dati, ecc. Quindi acquisisci l'output della pagina e voilà! Hai la tua email HTML!

AGGIORNATO CON CAVEAT !!!:
stavo usando la classe MailDefinition su alcune pagine aspx, ma quando ho provato a usare questa classe durante un processo del server in esecuzione, non è riuscito. Credo che fosse perché il metodo MailDefinition.CreateMailMessage () richiede un controllo valido a cui fare riferimento, anche se non sempre fa qualcosa. Per questo motivo, consiglierei il mio approccio utilizzando una pagina aspx o l'approccio di Mun utilizzando una pagina ascx, che sembra un po 'migliore.


Un'altra soluzione potrebbe essere quella di utilizzare AlphaMail per creare e inviare le tue e-mail utilizzando C # e il linguaggio dei modelli Comlang .
Timothy E. Johansson,

1
@JohnBubriski: lavoro che ho intorno problema di controllo lei ha citato in "aggiornato con caveat" usando new System.Web.UI.Control()come in: mailDefinition.CreateMailMessage("somebody@fake.com", iDictionaryReplacements, new System.Web.UI.Control()).
Teofilo

Sì, l'ho fatto anche io, ma dato l'avvento di Razor, questa sta diventando sempre meno una buona idea.
John Bubriski

Risposte:


73

Ci sono già un sacco di risposte qui, ma mi sono imbattuto in un ottimo articolo su come utilizzare Razor con i modelli di posta elettronica. Razor è stato inviato con ASP.NET MVC 3, ma MVC non è necessario per usare Razor. Questa è un'elaborazione piuttosto semplice per creare modelli di email

Come identifica l'articolo, "La cosa migliore di Razor è che a differenza del suo predecessore (webforms) non è legato all'ambiente web, possiamo facilmente ospitarlo fuori dal web e usarlo come motore di modelli per vari scopi".

Generazione di email HTML con RazorEngine - Parte 01 - Introduzione

Sfruttare i modelli Razor al di fuori di ASP.NET: non sono più solo per HTML!

Modelli di posta elettronica più intelligenti in ASP.NET con RazorEngine

Stackoverflow QA simile

Creazione di modelli utilizzando la nuova API RazorEngine

Utilizzo di Razor senza MVC

È possibile utilizzare Razor View Engine al di fuori di asp.net


1
+1 ma fai attenzione se gli utenti forniscono i modelli, poiché possono eseguire codice C # dal modello, dando loro molta più potenza nel tuo sistema di quanto probabilmente vorresti.
AaronLS

Cosa ne pensi della sicurezza. L'utilizzo di questo motore di template rende possibile forse formattare l'intero file system. Mi piace il motore, ma questo mi costringe a dare un'occhiata ad altri motori.
der_chirurg

55

Potresti anche provare a caricare un controllo, quindi visualizzarlo in una stringa e impostarlo come corpo 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();

Puoi quindi costruire la tua email come al solito:

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

Il controllo utente potrebbe contenere altri controlli, ad esempio un'intestazione e un piè di pagina, e sfruttare anche funzionalità come l'associazione dati.


In qualche modo mi è sfuggita questa risposta la prima volta ... bella. Simile alla mia soluzione, ma con un ascx invece di un aspx. Penso ancora che aspx sarebbe migliore, poiché offrirebbe una pagina completa, invece di un controllo, ma è proprio quello che penso.
John Bubriski

Sì, puoi usare entrambe le soluzioni ... Funzionano allo stesso modo. Uno dei vantaggi di questo approccio è la coerenza. Ad esempio, potresti mostrare a un utente un riepilogo dell'ordine e includere esattamente la stessa cosa nell'e-mail di conferma riutilizzando lo stesso controllo.
Mun

Punto minore ma ti manca una riga per dichiarare uno StringBuilder nel primo blocco di codice.
Kirschstein

9
L'esempio non spiega dove risiede il codice, è una pagina ?, perché LoadControl è un metodo di pagina / controllo.
Shrage Smilowitz

@Mun, carichi il controllo utente in una variabile chiamata ctrl e non lo fai mai più riferimento nel codice. Come dovrebbe funzionare?
The Muffin Man

35

Potresti provare la classe MailDefinition


4
Voglio solo sottolineare che questo è un bene per le email di base, ma non per nulla di complesso. La classe MailDefinition non supporta l'associazione dati. L'unica cosa che fa davvero è offrire la sostituzione delle stringhe. Tuttavia, è anche integrato nella Creazione guidata account di iscrizione.
John Bubriski

4
La classe MailDefinition deve ottenere un controllo per eseguire il rendering del contenuto basato su modelli .. Non così buono.
Yuki

17

Se desideri passare parametri come nomi utente, nomi di prodotti, ... ecc. Puoi utilizzare il motore di modelli open source NVelocity per produrre la tua email / HTML finale.

Un esempio di modello 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

Generazione del corpo del messaggio da MailTemplate.vm nella tua applicazione:

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

Il corpo del messaggio di posta elettronica del risultato è:

Un modello di email di esempio di ScarletGarden .

Per ogni esempio:

[Data: 12.02.2009] Nome: Voce 1, Valore: 09

[Data: 21.02.2009] Nome: Voce 4, Valore: 52

[Data: 01.03.2009] Nome: Voce 2, Valore: 21

[Data: 23.03.2009] Nome: elemento 6, valore: 24

Per modificare i modelli, forse puoi usare FCKEditor e salvare i tuoi modelli su file.


7

Il componente di posta elettronica Mail.dll include il motore dei modelli di posta elettronica:

Ecco la panoramica della sintassi:

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

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

</body>
</html>

E il codice che carica il modello, riempie i dati dall'oggetto c # e invia un'e-mail:

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

Puoi ottenere maggiori informazioni sul post del blog del motore dei modelli di email .

O semplicemente scarica il componente di posta elettronica Mail.dll e provalo.

Tieni presente che questo è un prodotto commerciale che ho creato.


6

Se la flessibilità è uno dei tuoi prerequisiti, XSLT potrebbe essere una buona scelta, che è completamente supportata da .NET framework e potresti persino consentire all'utente di modificare quei file. Questo articolo ( http://www.aspfree.com/c/a/XML/XSL-Transformations-using-ASP-NET/ ) potrebbe essere utile per iniziare (msdn ha maggiori informazioni a riguardo). Come detto da ScarletGarden NVelocity è un'altra buona scelta, ma preferisco XSLT per il suo supporto .NET framework "integrato" e indipendente dalla piattaforma.


Non ci avevo mai pensato prima, ma dopo aver provato molti altri metodi ho scoperto che funzionava benissimo in combinazione con l'aggiunta IXmlSerializabledell'interfaccia alle mie classi. In poche righe posso fare in modo che la mia classe riceva un'email.
cjbarth

Urgh, ho sognato incubi su XSLT. Probabilmente il linguaggio di programmazione / markup più non intuitivo con cui ho lavorato. E impossibile da mantenere per gli altri e anche per te stesso 1 mese dopo aver codificato per la prima volta il tuo XSLT.
PussInBoots

5

Penso che potresti anche fare qualcosa del genere:

Crea una pagina .aspx e inseriscila alla fine del metodo OnLoad o chiamala manualmente.

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

Non sono sicuro che ci siano potenziali problemi con questo, ma sembra che funzionerebbe. In questo modo, potresti utilizzare una pagina .aspx con funzionalità complete, invece della classe MailDefinition che supporta solo le sostituzioni di testo.


Sebbene la classe MailDefinition sia un buon inizio, è un po 'rudimentale. Questo metodo dovrebbe supportare molte più funzionalità come l'associazione dati e forse anche la traccia. Qualche idea su questo, o potenziali trucchi?
John Bubriski

Grande! Hai avuto problemi con esso?
John Bubriski

Consentirai quindi ai tuoi utenti di modificare i file .aspx quando devono apportare modifiche al modello di posta? Lo definirei un potenziale problema.
Bryan

Non lo penserei, almeno, non più rischioso di altri modelli che potrebbero modificare. Certo, se sapessero cosa stanno facendo, potrebbero causare danni, ma almeno in questo caso, è improbabile. Non sarebbe una pagina .aspx complessa, più un modello con segnaposto.
John Bubriski

È passato un po 'di tempo, lo so, ma ricordi la tua soluzione finale? Non sono riuscito a far funzionare questo particolare approccio con a Page, almeno quando si utilizza un metodo di estensione generico per il rendering. Così sono passato a UserControl; vedi la mia risposta di seguito. Finora sembra funzionare bene ... Sarei interessato a sapere come l'hai risolto in quel momento.
InteXX

4

Sicuramente puoi creare un modello html e ti consiglio anche un modello di testo. Nel modello puoi semplicemente mettere [BODY] nel punto in cui verrebbe posizionato il corpo e poi puoi semplicemente leggere nel modello e sostituire il corpo con il nuovo contenuto. È possibile inviare l'email utilizzando .Nets Mail Class. Devi solo scorrere l'invio dell'e-mail a tutti i destinatari dopo aver creato l'e-mail inizialmente. Ha funzionato benissimo per me.

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

Puoi ritagliare il materiale StreamReader e sostituirlo con File.ReadAllText (percorso)
John Sheehan

Questo è un buon inizio, ma fornisce solo funzionalità per un'intestazione e un piè di pagina. Questo non aiuta davvero con il corpo stesso.
John Bubriski

Il corpo tutto ciò che devi fare è inserire il contenuto del corpo desiderato nei campi HTMLBody e TextBody oppure puoi ovviamente archiviarli anche in file
Josh Mein

4

Ecco un'altra alternativa che utilizza le trasformazioni XSL per modelli di posta elettronica più complessi: Invio di posta elettronica basata su HTML da applicazioni .NET .


2
Come il collegamento. Grazie! Il mio cervello ha iniziato a girare e ho capito che potevo fare un ulteriore passo avanti e avere un modello XSLT che prende un oggetto serializzabile XML, o contratto dati WCF, direttamente nel formato html-email. All'improvviso avrei avuto modelli di posta elettronica "forte" attraverso classi serializzabili reali!
CodingWithSpike

2

Fai attenzione quando fai questo, i filtri SPAM sembrano bloccare l'html generato da ASP.net, apparentemente a causa di ViewState, quindi se hai intenzione di farlo assicurati che l'Html prodotto sia pulito.

Personalmente esaminerei l'utilizzo di Asp.net MVC per ottenere i risultati desiderati. o NVelocity è abbastanza bravo in questo


1

L'ideale sarebbe utilizzare una pagina .ASPX come modello in qualche modo, quindi dire al mio codice di servire quella pagina e utilizzare l'HTML restituito per l'email.

Potresti facilmente costruire una WebRequest per raggiungere una pagina ASPX e ottenere l'HTML risultante. Con un po 'più di lavoro, probabilmente puoi farlo senza WebRequest. Un PageParser e un Response.Filter ti consentirebbero di eseguire la pagina e catturare l'output ... anche se potrebbero esserci alcuni modi più eleganti.


1

Avevo un requisito simile su 1 dei progetti in cui dovevi inviare un numero enorme di e-mail ogni giorno e il cliente voleva il controllo completo sui modelli html per diversi tipi di e-mail.

a causa dell'elevato numero di e-mail da inviare, le prestazioni erano una preoccupazione primaria.

ciò che abbiamo creato è stato il contenuto statico nel server sql in cui si salva l'intero markup del modello html (insieme a segnaposto, come [UserFirstName], [UserLastName] che vengono sostituiti con dati reali in fase di esecuzione) per diversi tipi di email

quindi abbiamo caricato questi dati nella cache di asp.net, quindi non leggiamo i modelli html più e più volte, ma solo quando vengono effettivamente modificati

abbiamo fornito al cliente un editor WYSIWYG per modificare questi modelli tramite un modulo web di amministrazione. ogni volta che sono stati effettuati aggiornamenti, ripristiniamo la cache di asp.net.

e poi avevamo una tabella separata per i registri delle e-mail, dove veniva registrata ogni e-mail da inviare. questa tabella aveva campi chiamati emailType, emailSent e numberOfTries.

abbiamo semplicemente eseguito un lavoro ogni 5 minuti per tipi di email importanti (come registrazione di un nuovo membro, password dimenticata) che devono essere inviati al più presto

abbiamo eseguito un altro lavoro ogni 15 minuti per tipi di email meno importanti (come email promozionali, email di notizie, ecc.)

in questo modo non blocchi il tuo server che invia email ininterrottamente ed elabori le email in batch. una volta inviata un'e-mail, impostare il campo emailSent su 1.


Ma come hai gestito le collezioni?
Riri

1
Ho fatto anche questo e ha funzionato bene. Inoltre puoi storicamente tornare indietro e vedere i record delle e-mail inviate, se i rapporti fanno per te.
Mark Glorie

1

Si noti che le soluzioni aspx e ascx richiedono un HttpContext corrente, quindi non possono essere utilizzate in modo asincrono (ad esempio nei thread) senza molto lavoro.


1

Penso che la risposta facile sia MvcMailer. È il pacchetto NuGet che ti consente di utilizzare il tuo motore di visualizzazione preferito per generare messaggi di posta elettronica. Vedere il pacchetto NuGet qui e la documentazione del progetto

Spero che sia d'aiuto!


Hmm, strano che questa risposta non abbia avuto così tanta attenzione ?!
PussInBoots

1

DotLiquid è un'altra opzione. Specifichi i valori da un modello di classe come {{ user.name }}e poi in fase di esecuzione fornisci i dati in quella classe e il modello con il markup, e unirà i valori per te. È simile all'uso del motore di modelli Razor in molti modi. Supporta cose più complesse come i loop e varie funzioni come ToUpper. La cosa bella è che questi sono "sicuri" in modo che l'utente che crea i modelli non possa mandare in crash il tuo sistema o scrivere codice non sicuro come faresti con razor: http://dotliquidmarkup.org/try-online


0

Se siete in grado di consentire il permesso ASPNET e gli utenti associati a leggere e scrivere un file, si può facilmente utilizzare un file HTML con standard di String.Format()segnaposto ( {0}, {1:C}, ecc) per raggiungere questo obiettivo.

Leggi semplicemente nel file, come una stringa, usando le classi dallo System.IOspazio dei nomi. Una volta che hai quella stringa, passala come primo argomento a String.Format()e fornisci i parametri.

Tieni quella stringa in giro e usala come corpo dell'e-mail, e il gioco è fatto. Lo facciamo oggi su dozzine di siti (certamente piccoli) e non abbiamo avuto problemi.

Dovrei notare che questo funziona meglio se (a) non invii miliardi di e-mail alla volta, (b) non personalizzi ogni e-mail (altrimenti mangi un sacco di stringhe) e (c ) il file HTML stesso è relativamente piccolo.


0

Imposta il messaggio di posta elettronica IsBodyHtml = true

Prendi il tuo oggetto che contiene il contenuto della tua email Serializza l'oggetto e usa xml / xslt per generare il contenuto html.

Se vuoi fare AlternateViews, fai la stessa cosa che jmein usa solo un modello xslt diverso per creare il contenuto di testo normale.

uno dei maggiori vantaggi di questo è che se vuoi cambiare il tuo layout tutto quello che devi fare è aggiornare il template xslt.


0

Guarda SubSonic (www.subsonicproject.com). Stanno facendo esattamente questo per generare codice: il modello è ASPX standard e restituisce c #. Lo stesso metodo sarebbe riutilizzabile per il tuo scenario.


0

Userei una libreria di modelli come TemplateMachine . questo ti consente principalmente di mettere il tuo modello di email insieme al testo normale e quindi utilizzare le regole per inserire / sostituire i valori secondo necessità. Molto simile a ERB in Ruby. Ciò ti consente di separare la generazione del contenuto della posta senza legarti troppo pesantemente a qualcosa come ASPX ecc. Quindi una volta che il contenuto viene generato con questo, puoi inviare via email.


0

Mi piace la risposta di Raj. Programmi come ListManager e framework come DNN fanno cose simili e se è richiesto un facile editing da parte di utenti non tecnici, gli editor WYSIWYG per modificare l'HTML memorizzato in SQL sono un modo per lo più semplice e diretto di procedere e possono facilmente ospitare la modifica delle intestazioni indipendentemente dai piè di pagina, ecc, oltre a utilizzare i token per inserire valori dinamicamente.

Una cosa da tenere a mente se si utilizza il metodo sopra (o qualsiasi altro, in realtà) è essere rigorosi e attenti ai tipi di stili e tag che si consente agli editor di inserire. Se pensi che i browser siano pignoli, aspetta di vedere in che modo i client di posta elettronica eseguono diversamente la stessa cosa ...


0

Simile alla risposta di Canavar, ma al posto di NVelocity, utilizzo sempre " StringTemplate " che carico il modello da un file di configurazione, oppure carico un file esterno utilizzando File.ReadAllText () e imposto i valori.

È un progetto Java ma la porta C # è solida e l'ho usata in diversi progetti (l'ho usata solo per i modelli di posta elettronica utilizzando il modello in un file esterno).

Le alternative sono sempre buone.


0

Ecco un modo semplice utilizzando la classe WebClient :

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

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

    return htmlBody;
}

Quindi chiamalo in questo modo:

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

Ovviamente, il tuo CSS dovrà essere allineato per mostrare gli stili della pagina web nella maggior parte dei client di posta elettronica (come Outlook). Se la tua e-mail mostra contenuto dinamico (es. Nome cliente), ti consiglio di utilizzare QueryStrings sul tuo sito web per popolare i dati. (es. http://www.yourwebsite.com?CustomerName=Bob )


Perfetto, anche se penso che la maggior parte delle altre risposte lo faccia senza fare una richiesta web al sito, cioè dover ospitare il corpo dell'email sul tuo sito.
Rup

@Rup Comprensibile, ma tieni presente che molte volte le persone vogliono comunque vedere una "versione web" dell'e-mail. Questa soluzione funziona perfettamente per quello scenario.
ROFLwTIME

0

@bardev fornisce una buona soluzione, ma sfortunatamente non è l'ideale in tutti i casi. Il mio era uno di loro.

Sto usando WebForms in un sito Web (giuro che non userò mai più un sito Web - che PITA) in VS 2013.

Ho provato il suggerimento Razor, ma essendo un sito Web non ho ricevuto l'importantissimo IntelliSense che l'IDE offre in un progetto MVC. Mi piace anche usare il designer per i miei modelli, un posto perfetto per un UserControl.

Di nuovo Nix su Razor.

Quindi mi è venuto in mente questo piccolo framework (suggerimenti per @mun per UserControl e @imatoria per Strong Typing). Quasi l'unico potenziale problema che posso vedere è che devi stare attento a mantenere il tuo nome file .ASCX sincronizzato con il nome della sua classe. Se ti allontani, otterrai un errore di runtime.

FWIW: Nella mia prova almeno la chiamata RenderControl () non piace un controllo di pagina, quindi sono andato con UserControl.

Sono abbastanza sicuro di aver incluso tutto qui; fammi sapere se ho tralasciato qualcosa.

HTH

Utilizzo:

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

Classe base:

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

Classe "Fabbrica":

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

Classe modello:

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

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

Piè di pagina ASCX:

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

</body>
</html>

Modello 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" />

File di codice modello 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

Aiutanti:

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

Sto solo lanciando la libreria che sto usando nel mix: https://github.com/lukencode/FluentEmail

Rende le e -mail utilizzando RazorLight , utilizza lo stile fluente per creare e-mail e supporta più mittenti fuori dagli schemi. Viene fornito con metodi di estensione anche per ASP.NET DI. Semplice da usare, poche impostazioni, con testo normale e supporto HTML.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.