Archive

Archive for the ‘email рассылки’ Category

Автоматизация подписки на рассылку FeedBurner. Часть 3

March 9th, 2010 No comments

Заключительная часть трилогии о том, как взять feedburner’овскую капчу, заставить пользователя ввести её и подписать его на рассылку feedburner.

Часть 1, Часть 2

В этой статье разберем серверную часть программы – php-скрипт, задача которого обратиться к сервису feedburner, получить капчу, передать пользователю, принять расшифровку капчи от пользователя и передать feedburner. Я использовал ZendFramework, но в основном по мелочи.

Итак, весь скрипт состоит из двух больших блоков. Первый – для случая, когда мы только получаем капчу, второй – для случая, когда пользователь её уже расшифровал.

Когда мы обращаемся к фидбернеру в первый раз отрабатывает следующий скрипт:

$client = new Zend_Http_Client(/* здесь должна идти строка с адресом рассылки, которую генерирует feedburner */);
$client->setParameterPost(array(
	        'loc'  => 'ru_RU',
	        'uri'   => /* данные вашей рассылки */,
	        'email' => /* данные вашей рассылки */,
	    ));
$resp = $client->request('POST');	// выполняем POST запрос
$headers = $resp->getHeaders();
 
// меняем относительные пути на полные
$response =  str_replace('captcha?','http://feedburner.google.com/fb/a/captcha?', $resp);
$response =  str_replace('="/fb','="http://feedburner.google.com/fb', $response);
 
// В ответ на наш запрос feedburner генерирует форму
// для заполнения с рядом скрытых (hidden) полей.
// Значение этих полей нам нужно достать и отправить
// обратно фидбернеру при следующем обращении
// Здесь я опушу большую часть однотипных действий
$pos1 = strpos($response, 'action="');
$action = substr($response, $pos1 + 8);
$pos11 = strpos($action, '"');
$action = substr($action, 0, $pos11);
 
$pos1 = strpos($response, 'input type="hidden" name="uri"');
$uri = substr($response, $pos1 + 38);
$pos11 = strpos($uri, '"');
$uri = substr($uri, 0, $pos11);

А далее нам остается только сформировать собственный кусок кода HTML, который AJAX вернет клиенту:

<form>
	<input type="hidden" id="fbaction" name="fbaction" value=""/>
	<input type="hidden" id="fburi" name="fburi" value=""/>
	<input type="hidden" id="fbemail" name="fbemail" value=""/>
	<input type="hidden" id="fbtoken" name="fbtoken" value=""/>
	<input type="hidden" id="fbcookie" name="fbcookie" value=""/>
 
</form>

$action, $uri, $email, $token – то, что мы достали из кода, сгенерированного фидбернером. $headers[‘Set-cookie’] – куки которые, установил фидбернер, их также нужно передать.

А теперь рассмотрим действия, когда пользователь ввел капчу, которую предложил нам фидбернер и отправил данные в наш серверный скрипт.

// клиент для HTTP-запросов
$client = new Zend_Http_Client($action);
// устанавливаем параметры, которые получили в прошлый
// раз от фидбернера
$client->setParameterPost(array(
		'loc'  => 'ru_RU',
	        'token'  => $_GET['token'],
	        'uri'   => $_GET['uri'],
	        'captcha'   => $_GET['captcha'],
	        'email' => $_GET['email']
	    ));
// не забываем добавить куки
$cookie = Zend_Http_Cookie::fromString($_GET['cookie']);
$client->setCookie($cookie);
// делаем POST запрос к фидбернеру
$response = $client->request('POST');

Вот и все. В $response у нас попадет ответ от фидбернера. Он скажет, что, либо регистрация прошла успешно, либо мы неправильно ввели капчу, либо плохой e-mail и т.п. Я ничего лучше не придумал, как проверять полученный текст на наличие каких-то ключевых слов. Это, в общем-то, тривиальная задача.

Автоматизация подписки на рассылку FeedBurner. Часть 2

February 17th, 2010 No comments

В первой части я описал, зачем нам в принципе автоматизировать подписку FeedBurner. Коротко: автоматизация заключается в автоматической подписке электронной почты пользователя на рассылку FeedBurner при заполнении пользователем формы подписки на рассылку другого сервиса. В нашем примере используется сервис smartresponder.ru.

В этой статье я приведу javascript код клиентской части скрипта. Напомню, для взаимодействия с сервером используется технология AJAX. Также я использовал фреймворк JQuery.

Общий принцип взаимодействия таков. Javascript вызывает серверный PHP скрипт с помощью http-запросов с методом GET и передает туда все необходимые параметры. Серверный скрипт взаимодействует с сервисом FeedBurner и формирует html-документ, который возвращает клиентскому скрипту. Клиентский скрипт вставляет полученный html-код в страницу и обрабатывает результат.

Итак, одним из поставленных условий было то, что исходный код, предоставляемый smartresponder’ом не должен меняться. Поэтому первым делом средствами javascript и JQuery я меняю стандартную кнопку формы на собственную.

$(document).ready(function() {
	$('[name=SR_submitButton]').before('input name="SR_submitButton2" value=""');
	$('[name=SR_submitButton2]').attr('value', $('[name=SR_submitButton]').attr('value'));
	$('[name=SR_submitButton2]').attr('style', $('[name=SR_submitButton]').attr('style'));
	$('[name=SR_submitButton]').hide();
 
	$('[name=SR_submitButton2]').click(function(){
		My_submit();
	 });
});

SR_submitButton – имя кнопки формы, которую предоставляет smartresponder. Вместо неё мы создаем собственную кнопку с именем SR_submitButton2 (по ходу перенимая стиль и название исходной кнопки), а SR_submitButton скрываем (hide()). В качестве обработчика нажатия SR_submitButton2 вешаем собственную функцию My_submit(), код которой приведен ниже.

function My_submit(submit)
{
	var f = $('[name=SR_form]');
	if(submit && (SR_submit(f[0])))
	{
		$('[name=SR_form]').submit();
		return true;
	}else
	{
		if(!onSubscribeSubmit(f))
		{
			var iteration = $(f).data("iter");
			if(!iteration)
			{
				$(f).data("iter", 1);
			}else if(iteration > 2)
			{
				$(f).data("iter", 0);
				$('[name=SR_form]').submit();
			}else
			{
				$(f).data("iter", iteration + 1);
			}
		}
		return false;
	}
}

Кнопка SR_submitButton2 будет нажиматься до получения капчи и после ввода её пользователем. Соответственно в функции My_submit предусмотрено два варианта работы. Если в функцию был передан параметр submit равный true, то подразумевается, что с feedburner’ом мы уже разобрались, и данные готовы к отправке в smartresponder. Но перед этим вызовем стандартную smarteponder’овсую функцию SR_submit, которая проверит поля формы. Если проверка прошла успещно мы попадаем в тело оператора if и выполняется

$(’[name=SR_form]‘).submit(); – отправка данных в сервис smartresponder.

В противном случае данные передаются на обработку функции onSubscribeSubmit. Если последняя возвращает false – это говорит о безуспешной попытке ввода капчи.

К сожалению в FeedBurner наблюдается неприятный эффект с адресами, которые там уже зарегистрированы. При попытке подписки такого адреса, FeedBurner воспринимает это как ввод неверной капчи и присылает новую. В итоге получается что вне зависимости от ввода пользователя, ему присылается новая капча. Чтобы этого избежать я ограничил количество вводов капчи тремя попытками. Не получилось с трех попыток – делать нечего, переадресуем клиента на smartresponder, оставляя в покое FeedBurner. Иначе мы рискуем что клиент уйдет вообще ни с чем.

Теперь разберем функцию onSubscribeSubmit().

function onSubscribeSubmit(f)
{
	if(!(jQuery.data(document.body, 'email'))) 	// пытаемся прочесть ранее сохраненный параметр элемента body с именем email.
							// Его отсутствие говорит о том, что мы ещё не получали капчи от FeedBurner’а.
	{
		// берем из формы адрес подписчика и записываем как параметр body
		jQuery.data(document.body, 'email',  $('[name=field_email]').val());
		// здесь мы обращаемся к собственному серверному скрипту и передаем ему
		// в качестве параметра адрес электронной почты подписчика
		$.ajax({
		type: "GET",
		url: serverPath + 'fb_request.php?email=' + $('[name=field_email]').val(),
		dataType: "html",
		data: {},
		timeout: 30000,
			success: function(data) {
				// в случае успеха добавляем перед кнопкой текст с просьбой
				// ввести капчу и саму капчу, которую нам вернул скрипт
				$('.approvement').remove();
				$('[name=SR_submitButton2]').before('<div class="approvement"><span style="font-size: 10pt; font-family: Verdana;">'+
				prompt  + '</span>' +
				data + '</div>');
				return false;
			},
			error: function (XMLHttpRequest, textStatus, errorThrown) {
				return false;
			}
			});
	}else()
	{
		// если мы попали в эту ветку, значит мы обрабатываем нажатие
		// кнопки уже при введенной капче
		$('#fbresult').remove();     // удаляем старые результаты работы
		$.ajax({
		type: "GET",
		// все указанные ниже параметры, начинающиеся с fb присылаются при
		// предыдущем взаимодействии и вставляются в документ.
		// Теперь же их нужно передать обратно для корректного
		// взаимодействия с FeedBurner’ом
		url: serverPath + 'fb_request.php?email=' + $('#fbemail').attr('value') +
		'&token=' + $('#fbtoken').attr('value') +
		'&uri=' + $('#fburi').attr('value') +
		'&captcha=' + $('#fbcaptcha').attr('value') +
		'&action=' + $('#fbaction').attr('value') +
		'&cookie=' + $('#fbcookie').attr('value'),
		dataType: "html",
		data: {},
		timeout: 30000,
			success: function(data) {
				// вставляем полученный результат
				$('[name=SR_form]').before(data);
				// вызываем обработчик полученного результата
				return handleFbResult(f);
			},
			error: function (XMLHttpRequest, textStatus, errorThrown) {
				return false;
			}
		});
	}
}

Также надо объявить строку с предложением ввести капчу, которая используется в функции.

var prompt =  '<p style="font-size: 8pt;">' +
'Введите текст на картинке и повторно нажмите на кнопку Получить.</p>';

Ну а теперь осталось разобрать последнюю функцию – обработку результата отправления капчи. Наш серверный скрипт, получив ответ от FeedBurner’а, вернет кусок html кода, в котором будет элемент с. Нас интересует значение (value) этого элемента.

function handleFbResult(f)
{
	var result = $('#fbresult').attr('value');
	switch(result)
	{
		// в случае если подписка FeedBurner успешно активирована, либо
		// адрес уже находится в подписном листе
		case 'already':
		case 'success':
			$('.approvement').remove();
			My_submit(true);  // отправка в smartreponder
			return true;
		break;
		case 'repeat':
			// неправильный ввод – перезапрашиваем капчу
			jQuery.data(document.body, 'email', null);
			onSubscribeSubmit(f);
		return false;
		break;
		case 'invalid':
			// пользователь ввел некорректный email
			$(f).data("email", null);
			$(".approvement").html('<font style="font-size: 10pt; font-family: Verdana; color: red; font-weight: bold;">Некорректный email</font>');
			return false;
		break;
	}
}

Вот, собственно, и всё, что делает клиентский скрипт. В следующей статье рассмотрим серверную часть.

Автоматизация подписки на рассылку FeedBurner. Часть 1

February 12th, 2010 No comments

Проблема

Для начала объясню, зачем мне потребовалось автоматизировать подписку FeedBurner и почему это может быть полезно другим.

В интернете существует довольно много сервисов (в том числе бесплатных), которые позволяют одним делать email рассылки, а другим, на эти рассылки подписываться (smartresponder.ru, subscriber.ru, рассылки@mail.ru и т.д.). У каждого, конечно, есть свои достоинства и недостатки.

Так, например, есть сервис FeedBurner, от гугла. Он позволяет превратить rss-ленту блога в серию писем, что для многих очень удобно. Однако, кроме как отправлять новые посты блога, FeedBurner ничего не умеет.

В то же время помимо постов в блоге иногда возникает необходимость посылать дополнительные письма своим подписчикам (особенно для тех, у кого блог или сайт – инструмент ведения бизнеса). А для этого приходится использовать какой-либо другой сервис рассылки (например те, что были перечислены выше).

Как же быть с подписчиками? Просить подписаться на две рассылки сразу – вариант, прямо скажем, сомнительный: люди не любят оставлять свою электронную почту в интернете.
А почему бы не сделать следующим образом. Давайте напишем скрипт, который при оформлении подписки (не FeedBurner) будет сначала отправлять данные о e-mail в сервис FeedBurner и регистрироваться там, а уже потом переходить на стандартную для рассылки регистрацию.

Сказано – сделано, я написал скрипт для связи рассылки smartresponder.ru с FeedBurner. Поэтому весь дальнейший код, будет работать с формой, которая генерируется smartresponder’ом. Но, можно будет убедиться, что при небольших изменениях его можно будет использовать и с другими сервисами рассылок.

Теория

Проблема в том, что при подписке на рассылку в FeedBurner, последний генерит капчу для проверки на ботов. Эту капчу нужно получить и вывести пользователю, а потом его ввод передать обратно в сервис FeedBurner.

Ещё одно техническое условие: не вносить изменения в скрипт, который предоставляет smartresponder. Это условие я поставил для того, чтобы даже тот, кто ни в зуб ногой в веб-программировании, без проблем смог бы прикрутить этот дополнительный скрипт к уже имеющейся форме.

Архитектурно нам потребуется два модуля:

1. скрипт на Javascript, который:

  • после заполнения поля с e-mail передаст данные скрипту №2 и получит от него капчу FeedBurner’а.
  • после заполнения капчи передаст данные скрипту №2 и получит результат операции. В случае успеха перейдет на страницу регистрации в smartresponder’е.

2. скрипт на PHP, который:

  • Получает от первого скрипта данные с e-mail’ом, передает в FeedBurner. В ответ получает рисунок с капчей и дополнительные данные. После чего передает эту информацию обратно первому скрипту.
  • После ввода капчи передает её FeedBurner’у, получает результат и возвращает его первому скрипту.

Взаимодействие между первым и вторым скриптами будет происходить посредством AJAX. Иллюстрация:

1

2

По сути получается клиент-серверная архитектура. На стороне клиента – javascript, на сервере – php-скрипт, взаимодействующий с сервисов FeedBurner.

На этом пока всё. Во второй статье приведу код клиентской части. Там, кстати, я использовал JQuery. В третьей статье рассмотрим серверную сторону.