Per Nergård
Jan 17, 2013
  3395
(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
Plug-in manager is back in CMS 12

Plug-in manager is back in the UI, what is it and how can i use it?

Luc Gosso (MVP) | Oct 6, 2022 | Syndicated blog

Display Child Pages in Content Delivery API Response

The below example will implement an instance of IContentConverterProvider to customise the serialisation of PageData and output child pages in the...

Minesh Shah (Netcel) | Oct 4, 2022

Bring the Report Center back in Optimizely CMS 12

The Report Center has been a part of Optimizely CMS since its first debut in version 5R2 in 2008, but in CMS 12, it's removed! Don't despair! Make...

Tomas Hensrud Gulla | Oct 4, 2022 | Syndicated blog

Customizing Property Lists in Optimizely CMS

Generic property lists is a cool editorial feature that has gained a lot of popularity - in spite of still being unsupported (officially). But if y...

Allan Thraen | Oct 2, 2022 | Syndicated blog