Search code examples
c#mandrillmassmail

How do I prepare a list of mailaddresses to be sent to Mandrill if there are more addresses than fit in 1 request


I am developing a mass mailing client for our customers that uses Mandrill as a backend. in their FAQ, Mandrill states that the JSON request needs to be smaller than 10 MB. Because of this, I cannot just add all the addresses to a single request, but instead I need to send them in multiple requests.

I can see 2 methods: either split the list in groups (to have somewhat of a buffer zone) and send them per group, or send them in singles to each address at a time. I don't really like the second method, since that would spam the Mandrill API with trivial requests and could get me blacklisted. The first option would limit how many requests the Mandrill API receives and also reduce the stress on our own network, but I'm not sure on what method to use to split them.

  • Using a for loop with a counter and special logic when the counter reaches a certain number seems to me like a hacky solution that could easily break.
  • Splitting the list itself into chunks and processing each chunk separately is another option, but one that I don't quite know how to work out.

I don't know what the best method is of these 2, if there is a better 3rd method, or if there are general guidelines for the technical implementation of mass mailings. I've done some googling on this latter subject, but nothing really useful.


While the high-level solution suggested is helpful, I'm more interested in the technical side of splitting my list in 1000-5000 contacts. Is there a way to split an arbitrary List<Contact> of any size into pieces of, say, 4000 contacts each using C#?


Solution

  • You should probably be managing your actual mailing lists, groups and segments within Mandrill itself rather than externally - that way you can just send one request to the API and be done with it. You can even set up scheduled mailouts within Mandrill.

    In any case, yes you can split a List into arbitrary segments - one way is use the .Skip and .Take methods after importing System.Linq:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    public class Program
    {
        public static void Main()
        {
            IList<int> l = new List<int>();
            for(int i = 0; i < 5000; i++){
                l.Add(i);   
            }
    
            var a = l.Take(1000); //First 1000 items
            var b = l.Skip(1000).Take(1000); //Second 1000 items
            var c = l.Skip(2000); //Final 3000 items
    
            System.Console.WriteLine("a: " + a.Count());
            System.Console.WriteLine("b: " + b.Count());
            System.Console.WriteLine("c: " + c.Count());
        }
    }
    

    You're probably best writing an extension method to handle this so you can specify exactly how many items should be in each segment, but the basic principle is there - it's essentially just the same idea behind pagination.