Ne v kontakte Asocial programmer's blog

Пишем простой авторегистратор. Часть 5 - подтверждение по email.

Содержание

  1. Инструментарий
  2. Основы
  3. Боремся с капчей
  4. Подключаем антикапчу
  5. Подтверждение по email
  6. Пишем модуль для RegSubmitter

Давайте заглянем в наш актив. Сейчас мы уже умеем писать простые регистраторы, умеющие бороться с капчей при помощи антикапчи. От окончательного захвата мирового господства полной автоматизации процесса регистрации нас отделяет единственный барьер - подтверждение по почте. Его преодолением мы сегодня и займемся. Под нож снова пойдет toodoo.ru, который мы уже препарировали в самом начале.

Шаг 1 - анализ.

Прежде всего, надо проверить, требуется ли подтверждение вообще :) Если нет, то можно идти за пивом кефиром и наслаждаться воскресным отдыхом. Кроме того, бывает так, что подтверждение почты не является необходимым, но приносит какие-то бонусы. В таком случае вы вольны выбирать, надо вам подтверждать, или слишком лень. Я обычно подтверждаю, поскольку это придает профилю более человекоподобный вид.

Далее требуется выяснить, достаточно для подтверждения просто перейти по ссылке из письма, или надо совершить какие-то дополнительные действия. В случае с toodoo.ru после перехода на страницу нужно нажать на кнопку “Согласен” для завершения подтверждения. Поэтому нужно провести анализ этой формы, точно так же как мы анализировали на предмет защиты саму форму регистрации.

screen33.jpg

Шаг 2 - пишем код.

Для работы с почтой мы будем использовать PEAR модуль (не путать с модулями движка php) Net/POP3. На многих хостингах он уже установлен, а если нет - во вложении архив со скриптом и модулем.

Алгоритм действия таков:

  1. Подключаемся к серверу, авторизуемся.
  2. Получаем список всех писем.
  3. Начинаем перебирать их, запрашивая заголовки каждого письма.
  4. Если в поле отправителя письма указан адрес сервиса, в котором мы регистрируемся - это нужное нам письмо. Если нет - ищем дальше.
  5. Из письма извлекаем ссылку на страницу подтверждения. (Тут нам снова понадобятся регулярные выражения).
  6. Если сервис того требует, совершаем дополнительные действия для завершения подтверждения.
  7. ???
  8. PROF1T!

В случае с toodoo.ru, нам придется из страницы подтверждения добыть уникальный ключ (опять регулярки) и отправить один POST-запрос.

Собственно, вот код, он основан на коде из 2 статьи:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?php
header('Content-Type: text/html; charset=UTF-8');
// Функция, производящая регистрацию
function register($login, $email, $password)
{
	// Все POST-параметры, которые надо отправить
	$post = array(
		'agree' => 1, // Да, мы согласны с правилами ;-)
		'profile_is_female' => 0, // Укажем пол
		'profile_nick_name' => $login, // Наш логин
		'user_email' => $email, // email
		'user_password' => $password, // пароль
		'user_password_repeat' => $password,// повторим пароль
	);

	// Особая, curl-ная магия
	$ch = curl_init(); // Инициализируем сессию
	curl_setopt($ch, CURLOPT_URL,"http://toodoo.ru/account/signup"); // задаем адрес обработчика формы
	curl_setopt($ch, CURLOPT_POST, 1); // Указываем, что нам нужно отправить POST-запрос
	curl_setopt($ch, CURLOPT_POSTFIELDS, $post); // Передаем POST-параметры
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Результат нам нужно вернуть в переменную, а не на экран
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // Переходить по редиректам
	// Генерируем временный файл для cookies, чтобы они не терялись между запросами-редиректами
	$temp = tempnam('.', '__');
	curl_setopt($ch, CURLOPT_COOKIEJAR, $temp);
	unlink($temp);

	// Запускаем запрос!
	$result = curl_exec($ch);

	curl_close ($ch); // Закрываем сессию

	// Проверяем на успешность регистрации
	if(strstr($result, 'Поздравляем, ты успешно зарегистрировался в toodoo!'))
	{
		return true;
	}
	else
	{
		return false;
	}
}

// Параметры регистрации. Их можно задавать руками, или считывать из файла - на ваше усмотрение.
$login = 'autoreg-test';
$email = 'autoreg-test@yandex.ru';
$password = '*';
// Данные для авторизации на почтовом сервере
$pop3_server = 'pop.yandex.ru';
$pop3_login = 'autoreg-test';
$pop3_password = '';

$step = $_GET['step']; // Текущая стадия

// Выводим, что мы будем регать
echo "Логин: $login, пароль: $password, email: $email<br/>";

// Начало регистрации
if($step == 'reg')
{
	// Регаем
	if(register($login, $email, $password))
	{
		echo 'Успешно зарегистрирован';
		echo '<br><a href="'.basename(__FILE__).'?step=confirm">подтверждение по email</a>';
	}
	else
	{
		echo '<b>Ошибка регистрации</b>';
		echo '<br><a href="'.basename(__FILE__).'">Еще раз</a>';
	}
}
// Завершение регистрации (подтверждение)
else if($step == 'confirm')
{
	// Подключаем библиотеку для работы с POP3
	require('PEAR/POP3.php');

	// Создаем POP3-клиент
	$api = new Net_POP3();

	// Подключаемся к почтовому серверу
	if($api=>connect($pop3_server , 110 ) !== true)
	{
		echo 'Не удалось подключиться к серверу';
		echo '<br><a href="'.basename(__FILE__).'?step=confirm">Еще раз</a>';
		die();
	}

	// Авторизуемся
	if($api->login($pop3_login , $pop3_password ) !== true)
	{
		echo 'Не удалось авторизоваться';
		echo '<br><a href="'.basename(__FILE__).'?step=confirm">Еще раз</a>';
		die();
	}

	$list = $api->getListing(); // Получаем список писем в ящике

	// Ищем нужное письмо - скачиваем заголовки поочередно для всех писем и проверяем адрес отправителя
	foreach($list as $item)
	{
		$headers = $api->getParsedHeaders($item['msg_id']); // Скачиваем заголовки

		// Если отправитель совпадает с нужним нам, то приступаем к обработке
		if(strstr($headers['From'], 'toodoo.ru'))
		{
			$body = $api->getBody($item['msg_id']); // Скачиваем все письмо

			// Вытаскиваем уникальную ссылку
			preg_match('#http://toodoo.ru/confirm/contact\?code=\S+#i', $body, $matches);

			// Особая, curl-ная магия
			$ch = curl_init(); // Инициализируем сессию
			curl_setopt($ch, CURLOPT_URL,$matches[0]); // задаем адрес страницы подтверждения
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Результат нам нужно вернуть в переменную, а не на экран
			curl_setopt($ch. CURLOPT_FOLLOWLOCATION, 1); // Переходить по редиректам
			$result = curl_exec($ch); // Выполняем запрос

			// Мы, часом, еще не подтвердили?
			if(strstr($result, 'Видимо адрес по этой ссылке был уже подтвержден.'))
			{
				echo 'Что-то пошло не так, либо аккаунт уже подтвержден.';
				echo '<br><a href="'.basename(__FILE__).'?step=confirm">Еще раз</a>';
				break;
			}

			// У toodoo.ru требуется отправить дополнительную форму о том, что мы действительно подтверждаем регистрацию

			// Добываем уникальный ключ
			preg_match('#<input type="hidden" name="code" value="([^"]+)">#', $result, $matches);

			// Формируем поля запроса
			$post = array(
				'code'	=> $matches[1],
				'agree'	=> 'Добавить',
			);

			// Отправляем форму
			curl_setopt($ch, CURLOPT_URL,"http://toodoo.ru/confirm/contact"); // задаем адрес обработчика формы
			curl_setopt($ch, CURLOPT_POST, 1); // Указываем, что нам нужно отправить POST-запрос
			curl_setopt($ch, CURLOPT_POSTFIELDS, $post); // Передаем POST-параметры
			$result = curl_exec($ch); // Выполняем запрос

			curl_close ($ch); // Закрываем сессию

			// Мавр сделал свое дело, мавр может уходить.
			echo 'Аккаунт успешно подтвержден!';
			break;
		}
	}
}
else
{
	echo '<br><a href="'.basename(__FILE__).'?step=reg">Начать регистрацию</a>';
}

// Все!  ;-)
?>

В коде опять есть пара синтаксических ошибок, но я думаю, для вас они проблемы не представляют :) Скачать весь скрипт: toodoo.zip

Итоги.

Теперь вы знаете все, что нужно для успешного написания авторегистратора практически к любому сервису. Поздравляю :)

Но если вы думаете, что это конец - то вы жестоко заблуждаетесь, я те позволю так просто от меня отделаться ;) В рамках цикла будет еще целых 2 статьи. Заключительной частью будет разумно сделать ответы на ваши вопросы по авторегистраторам, так что не стесняйтесь их задавать, а вот содержимое 6 части я пока придержу в секрете. Пусть это будет небольшим сюрпризом ;)

Вам удачного программирования, а я пойду разучивать это произведение :)

P.S. Vivaldi — Summer Storm (by Children of Bodom)