-
Notifications
You must be signed in to change notification settings - Fork 32
Message Templates
The plain or HTML text of a mail message with its {placeholders}
actually already can be called a template on the top level.
Templates in the sense of MailMergeLib
offer to include any parts of text which shall be used or not depending on certain conditions. In the code you only have to define the condition for certain text parts. You do not have to include the text itsself. This way, the text may change without code modification.
The number of templates inside a mail message is unlimited.
A sample will make this more clear: Assume you want to choose the personalized salutation in a mail message depending on how close the relation to the recipient is.
You could code like this - not the recommended way:
var variables = new Dictionary<string, string>
{ { "firstName", "John" }, { "lastName", "Specimen" }, { "gender", "m" } };
var salutationType = Logic.GetSalutationType(...); // e.g. "friend"
switch (salutationType)
{
case "friend":
variables.Add("salutation", $"Hi {variables["firstName"]}");
break;
case "well-known":
variables.Add("salutation", $"Dear {(variables["gender"] == "m" ? "Mr." : "Mrs.")} {variables["lastName"]}");
break;
case "formal":
default:
variables.Add("salutation", "Dear Sir or Madam");
break;
}
var mmm = new MailMergeMessage("The Subject", "some text {salutation} more text");
// add addresses and other stuff here
new MailMergeSender().Send(mmm, (object) variables);
This has several disadvantages:
- The resulting salutation value is a combination of values from other variables
- Adding text formatting e.g. for the lastName is not possible, or you would have add this also to the code
- The code contains literal text, which is not part of the mail message definition
- Adding another salutationType requires changes in code and thus a recompiled assembly
- Making a distinction between plain and HTML text would require additional program logic
Let's prepare an xml file with the following content, which will be de-serialized later.
<MailMergeMessage>
<PlainText><![CDATA[some text {:template(Salutation)} more text]]></PlainText>
<HtmlText><![CDATA[<html><head></head><body>some text {:template(Salutation)} more text</body></html>]]></HtmlText>
<Templates>
<Template Name="Salutation">
<Text DefaultKey="formal">
<Part Key="friend" Type="Plain"><![CDATA[Hi {firstName}\n]]></Part>
<Part Key="friend" Type="Html"><![CDATA[Hi <b>{firstName}</b><br/>]]></Part>
<Part Key="well-known" Type="Plain"><![CDATA[Dear {gender:choose(m):Mr|Mrs} {lastName}\n]]></Part>
<Part Key="well-known" Type="Html"><![CDATA[Dear {gender:choose(m):Mr|Mrs} <b>{lastName}</b><br/>]]></Part>
<Part Key="formal" Type="Plain"><![CDATA[Dear Sir or Madam\n]]></Part>
<Part Key="formal" Type="Html"><![CDATA[<b>Dear Sir or Madam</b><br/>]]></Part>
</Text>
</Template>
</Templates>
</MailMergeMessage>
Note This sample applies the built-in Choose Formatter Extension: {gender:choose(m):Mr.|Mrs.}.
var variables = new Dictionary<string, string>
{ { "firstName", "John" }, { "lastName", "Specimen" }, { "gender", "m" } };
var mmm = MailMergeMessage.Deserialize(@"path-to-xml-file", Encoding.UTF8);
mmm.Templates["Salutation"].Key = Logic.GetSalutationType(...); // e.g. "friend"
// add addresses and other stuff here
new MailMergeSender().Send(mmm, (object) variables);
This is much better:
- The template gets all variables to build the desired result without additionally coded data
- Get the plain and HTML text parts in a simple and transparent way
- Format plain and HTML text parts independently with no code
- For a new SalutationType just add another part to the "Salutation" Template with no code
- Need the message for another language? Edit the xml file and you're done.
There are two strategies for using Templates
in messages:
- Add
Templates
to theMailMergeMessage
so they become a fixed part of them - Manage Templates apart from
MailMergeMessage
s
This way the Templates
become a fixed part of the MailMergeMessage
. You can serialize the message to the file system and Templates
will be included.
var mmm = new MailMergeMessage();
// some more stuff
mmm.Templates.Clear();
mmm.Templates.Add(new Template("Salutation",
new Parts
{
new Part(PartType.Plain, "Hi", "Hi {FirstName}"),
new Part(PartType.Html, "Hi", "Hi <b>{FirstName}</b><br>"),
new Part(PartType.Plain, "Dear", "Dear {FirstName}"),
new Part(PartType.Html, "Dear", "Dear <b>{FirstName}</b><br>"),
new Part(PartType.Plain, "Formal", "Dear Sir or Madam"),
new Part(PartType.Html, "Formal", "<b>Dear Sir or Madam</b><br>"),
}, "Formal"));
mmm.Serialize("path-to-message", Encoding.UTF8);
You can attach the Templates
to different MailMergeMessage
. For this it will be useful to save the Templates
to a file, and Add the Templates
to new messages as needed.
var templates = new Templates
{
new Template("Salutation",
new Parts
{
new Part(PartType.Plain, "Hi", "Hi {FirstName}"),
new Part(PartType.Html, "Hi", "Hi <b>{FirstName}</b><br>"),
new Part(PartType.Plain, "Dear", "Dear {FirstName}"),
new Part(PartType.Html, "Dear", "Dear <b>{FirstName}</b><br>"),
new Part(PartType.Plain, "Formal", "Dear Sir or Madam"),
new Part(PartType.Html, "Formal", "<b>Dear Sir or Madam</b><br>"),
}, "Formal")
};
templates.Serialize("path-to-template-file", Encoding.UTF8);
var mmm1 = new MailMergeMessage();
mmm1.Templates.AddRange(Templates.Deserialize("path-to-template-file", Encoding.UTF8));
//later: save the message without the templates
mmm1.Templates.Clear();
mmm1.Serialize("path-to-message-1", Encoding.UTF8);
var mmm2 = new MailMergeMessage();
mmm2.Templates.AddRange(Templates.Deserialize("path-to-template-file", Encoding.UTF8));
//later
mmm2.Templates.Clear();
mmm2.Serialize("path-to-message-2", Encoding.UTF8);
- You do not need
Parts
with bothPartType
s,PartType.Plain
andPartType.Html
.PartType.Plain
can be used for plain and HTML messages. If noPartType.Html
exists for a HTML message, thenPartType.Plain
will be inserted. - If the
Parts
only contain one or twoPartType
s with the sameKey
name, the firstPart
will be inserted if theDefaultKey
of theTemplate
is null. - Trying to add a
Part
with an existingKey
name for thePartType
will throw an exception.