Don't miss out Virtual Happy Hour this Friday (April 26).

Try our conversational search powered by Generative AI!

Per Nergård
Jan 17, 2013
  3924
(1 votes)

Programmatically add recipients to an EPiServer Mail recipient list.

I’ve been tinkering a bit with EPiServer Mail recently and the customer wanted the site visitors to be able to subscribe to the site newsletter using the standard built in source.

As you may or may not know the standard mail recipient source only have support for importing recipients from a csv or xml file.

Lucky for me the standard source have some nice methods but on the other side most are private so I used reflector to extract what I needed.

You need to create a Recipient list through importing at least one dummy recipient. The name given to the list is the one we will use to identify it in code.

Below is a code snippet with some comments. I’ve removed the AddSubscriber method in the snippet but it’s included in the complete example user control you can download from the code section. See link at the bottom of this post. In the example you can also see how you can unsubscribe a recipient.

Snippet:

1 //Instantiate a source object 2 EPiServer.Mail.Sources.Internal.Source store = new EPiServer.Mail.Sources.Internal.Source(); 3 4 //From the source we can get the recipientcontainer by name. 5 RecipientContainer container = store.GetRecipientContainer("Recipientlist"); 6 7 //If we don't do a dupe check it's possible to add the same address several times to the same recipientlist. 8 RecipientCollection collection = container.GetRecipients(); 9 var rcp = collection.FirstOrDefault<Recipient>(p => p.Email == textBoxEmail.Text); 10 if (rcp == null) 11 { 12 //Create a new recipent with the given email address. 13 //It's possible to add attributes ie surname, lastname etc to the recipient using 14 //EPiServer.Mail.Core.Attribute. These attributes can be used to personalize the email. 15 Recipient subscriber = new Recipient(textBoxEmail.Text.Trim(), false, null); 16 AddRecipient(subscriber, container, null); 17 }
Code section link:

Example at the code section

Jan 17, 2013

Comments

Jan 17, 2013 07:49 PM

It's nice to see a blog on customizing and extending Mail!

Mar 17, 2013 01:59 PM

Very nice Per. This might just be what I have been looking for!

Mar 17, 2013 02:39 PM

its a shame the example isnt for epimail 7. Im hoping its not too difficult to tweak it to make it work.

Jonathan Roberts
Jonathan Roberts Apr 16, 2013 03:18 PM

Im using Episerver 6 R2 and I cant see how I would add a user to a subscription list and set up pages to subscribe to. I have seen a blog talking about EPSUBSCRIBE but I have no idea what this is and where to set it to TRUE. Do you know of any step by step guides regarding Subscriptions using the CMS? Thanks Jonathan

Apr 22, 2013 08:29 AM

Jonathan: You can read this link http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-6/EPiServer-CMS-60/Subscription---Configuration/.

If I were you I would install a clean demo site and have a look at the demo subscription type.

Don't forget to activate the scheduledjob aswell.

Note that EPiServer subscriptions (not the same as EPi mail) by default only works for logged in users. This is because all subscription info is added to the logged in users profile.

Neil Perry
Neil Perry Apr 30, 2013 11:16 AM

Thanks for this, I am having difficulty adding attributes, would I need to call the store procedures

spEPiServerMailAddAttribute
spEPiServerMailAddAttributeValue

Or is there an API method? I have the Recipient, RecipientContainer and an AttributeCollection but want to add the AttributeCollection values into the database against the Recipient???

or should I implement custom IRecipientSource, the standard gives me everything I need if I can add the Attributes

Apr 30, 2013 01:56 PM

EPiDev: I don't have access to the machine that I did this on. But I think you should be able to do it through an API call.
I think that it should be possible through either when you create the new Recipient. or Add the recipient.

Check the null parameters for what could go in there.

Neil Perry
Neil Perry Apr 30, 2013 02:05 PM

Thanks - Yes, I have now coded a working solution and run some basic tests.

example call e.g Newsletter (RegisterFormModel not shown)

-------------------------------------------

///


/// Add to Newsletter Subscription List
///

///
private void NewsletterSubscription(RegisterFormModel formModel)
{
// Create Attributes
AttributeCollection ac = new AttributeCollection();
ac.Add(new EPiServer.Mail.Core.Attribute("Title", formModel.Title);
ac.Add(new EPiServer.Mail.Core.Attribute("Givenname", formModel.FirstName);
ac.Add(new EPiServer.Mail.Core.Attribute("Surname", formModel.Surname);

// Get recipient list to add to
RecipientLists recipientList = new RecipientLists();
recipientList.Email = formModel.Email;
recipientList.AttributeCollection = ac;
recipientList.Container = "Newsletter"; // example hard coded as named stored in global and RecipientList created using IInitializableModule

// Subscribe to recipient list
recipientList.Subscribe();

}

------------------------------------------- RecipientLists class -------------------------------------------
public class RecipientLists
{
///
/// Subscribers email address
///

public string Email { get; set; }
///
/// Subscribers extended attributes
///

public AttributeCollection AttributeCollection { get; set; }
///
/// Recipient List Container name
///

public string Container { get; set; }


///
/// Recipient Lists
///

public RecipientLists()
{
}

#region Public Methods

public void Subscribe()
{

// Instantiate a source object
Source store = new Source();

// From the source we can get the recipientcontainer by name.
RecipientContainer container = store.GetRecipientContainer(this.Container);

// If we don't do a dupe check it's possible to add the same address several times to the same recipientlist.
if (container != null)
{
RecipientCollection collection = container.GetRecipients();
var rcp = collection.FirstOrDefault(p => p.Email == this.Email);
if (rcp == null)
{
// Create a new recipent with the given email address.
Recipient subscriber = new Recipient(this.Email.Trim(), false, this.AttributeCollection);
AddRecipient(subscriber, container, subscriber.Attributes);
}
}

}

#endregion

#region Private Methods
///
/// Add a Recipient
///

///
///
///
private void AddRecipient(Recipient recipient, RecipientContainer recipientContainer, AttributeCollection attributes)
{

var databaseHandler = ServiceLocator.Current.GetInstance();

databaseHandler.ExecuteTransaction(() =>
{
Guid recipientId = (Guid)databaseHandler.GetScalar("spEPiServerMailAddRecipient", new object[] { recipient.Email, recipient.IsUnsubscribed, recipientContainer.ID });

// Update Number Of Recipients
if (recipientId != null)
{
databaseHandler.GetScalar("spEPiServerMailUpdateRecipientContainer", new object[] { recipientContainer.ID, recipientContainer.Name, recipientContainer.NumOfRecipients + 1 });
}

// Add Attribute Values
AddAttributeValues(recipientId, recipient.Attributes, recipientContainer, databaseHandler);
});

}

///
/// Add Attribute Values to recipient Container and add recipients value for an attribute
///

///
///
///
///
private void AddAttributeValues(Guid recipientId, AttributeCollection attributes, RecipientContainer recipientContainer, IDatabaseHandler databaseHandler)
{

List containerAttributes = new List();

// Populate container Attributes
using (IDataReader dr = databaseHandler.GetReader("spEPiServerMailGetAttributeNamesByContainer", new object[] { recipientContainer.ID }))
{
while (dr.Read())
{
ContainerAttribute containerAttribute = new ContainerAttribute();
containerAttribute.ID = dr.GetInt32(dr.GetOrdinal("intID"));
containerAttribute.Name = dr.GetString(dr.GetOrdinal("strName"));
containerAttributes.Add(containerAttribute);
}
}

var index = 1;
foreach (EPiServer.Mail.Core.Attribute attribute in attributes)
{
int attributeId;

// Check if attribute exists in Container List
var containerAttribute = containerAttributes.FirstOrDefault(x => x.Name == attribute.Name);
if (containerAttribute != null)
{
attributeId = containerAttribute.ID;
}
else
{
// Adds an attribute to a recipient container
attributeId = Convert.ToInt32(databaseHandler.GetScalar("spEPiServerMailAddAttribute", new object[] { attribute.Name, index, recipientContainer.ID }));
}

// Check if attributeId has been set
if (attributeId != 0)
{
// Adds a recipients value for an attribute
databaseHandler.GetScalar("spEPiServerMailAddAttributeValue", new object[] { attributeId, recipientId, attribute.Value });
}

index++;

}
}
#endregion


#region Private
///
/// Container Attribute
///

private class ContainerAttribute
{
public int ID { get; set; }
public string Name { get; set; }
}
#endregion
}

Marcus Andersson
Marcus Andersson Mar 27, 2014 11:03 AM

Per's solution works for EPiServer Mail 5, but does anyone know if it can be done in a similar way when using EPiServer Mail 7?

The reason I ask is because we want to be able to send multiple (unique) mails to a single recipient.

Please login to comment.
Latest blogs
Solving the mystery of high memory usage

Sometimes, my work is easy, the problem could be resolved with one look (when I’m lucky enough to look at where it needs to be looked, just like th...

Quan Mai | Apr 22, 2024 | Syndicated blog

Search & Navigation reporting improvements

From version 16.1.0 there are some updates on the statistics pages: Add pagination to search phrase list Allows choosing a custom date range to get...

Phong | Apr 22, 2024

Optimizely and the never-ending story of the missing globe!

I've worked with Optimizely CMS for 14 years, and there are two things I'm obsessed with: Link validation and the globe that keeps disappearing on...

Tomas Hensrud Gulla | Apr 18, 2024 | Syndicated blog

Visitor Groups Usage Report For Optimizely CMS 12

This add-on offers detailed information on how visitor groups are used and how effective they are within Optimizely CMS. Editors can monitor and...

Adnan Zameer | Apr 18, 2024 | Syndicated blog

Azure AI Language – Abstractive Summarisation in Optimizely CMS

In this article, I show how the abstraction summarisation feature provided by the Azure AI Language platform, can be used within Optimizely CMS to...

Anil Patel | Apr 18, 2024 | Syndicated blog

Fix your Search & Navigation (Find) indexing job, please

Once upon a time, a colleague asked me to look into a customer database with weird spikes in database log usage. (You might start to wonder why I a...

Quan Mai | Apr 17, 2024 | Syndicated blog