Как подготовить список почтовых адресов для отправки в Mandrill, если в одном запросе больше адресов, чем умещается
Я разрабатываю клиент массовой рассылки для наших клиентов, который использует Mandrill в качестве бэкэнда. В своих часто задаваемых вопросах Mandrill утверждает, что JSON-запрос должен быть меньше 10 МБ. Из-за этого я не могу просто добавить все адреса в один запрос, но вместо этого мне нужно отправить их в нескольких запросах.
Я вижу 2 способа: либо разделить список на группы (чтобы иметь некоторую буферную зону) и отправить их по группам, либо отправить их по одному на каждый адрес за раз. Мне не очень нравится второй метод, так как он спамит Mandrill API с помощью тривиальных запросов и может попасть в черный список. Первый вариант ограничил бы количество запросов, которое получает Mandrill API, а также уменьшил бы нагрузку на нашу собственную сеть, но я не уверен, какой метод использовать для их разделения.
- Использование цикла for со счетчиком и специальной логикой, когда счетчик достигает определенного числа, кажется мне хакерским решением, которое может легко сломаться.
- Разделение самого списка на куски и обработка каждого чанка отдельно - это еще один вариант, но я не совсем понимаю, как с ним работать.
Я не знаю, какой из этих двух методов лучший, если есть лучший третий метод или есть общие рекомендации по технической реализации массовых рассылок. Я немного погуглил по этому последнему вопросу, но ничего по-настоящему полезного.
Хотя предложенное высокоуровневое решение полезно, меня больше интересует техническая сторона деления моего списка на 1000-5000 контактов. Есть ли способ разбить произвольный List<Contact>
любого размера на кусочки, скажем, 4000 контактов каждый с использованием C#?
2 ответа
Вы, вероятно, должны управлять своими фактическими списками рассылки, группами и сегментами внутри самой Mandrill, а не извне - таким образом, вы можете просто отправить один запрос в API и покончить с этим. Вы даже можете настроить запланированные рассылки в Mandrill.
В любом случае, да, вы можете разбить список на произвольные сегменты - один из способов - использовать методы.Skip и.Take после импорта 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());
}
}
Вероятно, вам лучше всего написать метод расширения, чтобы справиться с этим, чтобы вы могли точно указать, сколько элементов должно быть в каждом сегменте, но основной принцип есть - это по сути та же идея, лежащая в основе разбиения на страницы.
Большинство пользователей, которые осуществляют массовую отправку, обычно разбивают свои списки на группы по 1000-5000 получателей, так как это количество получателей балансирует, используя преимущества пакетной отправки (что может значительно увеличить скорость отправки нам электронных писем, поскольку вы не открываете отдельные подключений для каждого получателя), хотя он по-прежнему достаточно мал, чтобы при возникновении проблем, требующих дальнейшего устранения неполадок, вы не копаетесь в информации для гораздо большего числа получателей. Отправка отдельных электронных писем не запрещена и не внесет вас в черный список с Mandrill, в частности - многие отправители делают это, потому что они отправляют транзакционные или высоко персонализированные электронные письма. Однако для вас это неэффективно, если вы обычно отправляете один и тот же контент. Пакетная обработка значительно увеличивает количество отправляемых нам сообщений, и тогда Mandrill будет обрабатывать список получателей и эффективно помещать в очередь сообщения. Возможно, вы захотите установить preserve_recipients
Параметр также равен false при пакетной обработке, особенно если вы отправляете тысячи получателей за один вызов API.