Views: 2975
Number of votes: 1
Average rating:

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

Jeff.Wallace
(By Jeff.Wallace, 1/17/2013 8:49:31 PM)

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

john.walsh
(By john.walsh, 3/17/2013 2:59:45 PM)

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

john.walsh
(By john.walsh, 3/17/2013 3:39:29 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
(By Jonathan Roberts, 4/16/2013 5:18:24 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

per.nergard
(By per.nergard, 4/22/2013 10:29:32 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
(By Neil Perry, 4/30/2013 1:16:18 PM)

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

per.nergard
(By per.nergard, 4/30/2013 3:56:46 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
(By Neil Perry, 4/30/2013 4:05:37 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
(By Marcus Andersson, 3/27/2014 12:03:57 PM)

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.