Per Nergård
Jan 17, 2013
  3961
(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
Opti ID overview

Opti ID allows you to log in once and switch between Optimizely products using Okta, Entra ID, or a local account. You can also manage all your use...

K Khan | Jul 26, 2024

Getting Started with Optimizely SaaS using Next.js Starter App - Extend a component - Part 3

This is the final part of our Optimizely SaaS CMS proof-of-concept (POC) blog series. In this post, we'll dive into extending a component within th...

Raghavendra Murthy | Jul 23, 2024 | Syndicated blog

Optimizely Graph – Faceting with Geta Categories

Overview As Optimizely Graph (and Content Cloud SaaS) makes its global debut, it is known that there are going to be some bugs and quirks. One of t...

Eric Markson | Jul 22, 2024 | Syndicated blog

Integration Bynder (DAM) with Optimizely

Bynder is a comprehensive digital asset management (DAM) platform that enables businesses to efficiently manage, store, organize, and share their...

Sanjay Kumar | Jul 22, 2024

Frontend Hosting for SaaS CMS Solutions

Introduction Now that CMS SaaS Core has gone into general availability, it is a good time to start discussing where to host the head. SaaS Core is...

Minesh Shah (Netcel) | Jul 20, 2024

Optimizely London Dev Meetup 11th July 2024

On 11th July 2024 in London Niteco and Netcel along with Optimizely ran the London Developer meetup. There was an great agenda of talks that we put...

Scott Reed | Jul 19, 2024