Описание протокола Mail.Ru агента
Приветствую!
Сегодня я расскажу про устройство MRIM протокола (протоколом Mail.Ru агента).
Сразу оговорюсь: есть официальное описание протокола, но оно устаревшее и практически не актуальное.
Найти его можно здесь: http://agent.mail.ru/ru/developers/protocol.html
Протокол исследовался мной с помощью снифера WireShark, официального агента версии 5.2 и QIP Infium версии 9024 (как не странно, у официального агента и у QIP поведение немного разное).
В статье будут фрагменты кода из моего класса MRIM.php (v3).
Итак, начнём.
MRIM (MMP) — бинарный протокол. Следовательно, при работе с сокетом необходимо использовать бинарно-безопасные функции fread и fwrite вместо текстовых fgets и fputs.
Рекомендованный сервер для подключения можно получить отсюда:
mrim.mail.ru:2042 — будет получен сервер с любым портом для подключения (обычно, 2041)
mrim.mail.ru:443 — будет получен сервер с портом для подключения 443. Полезно при работе через прокси-сервер.
Сервер будет получен в формате IP:PORT с символом конца строки после него.
Далее необходимо установить соединение с полученным сервером.
В протоколе используется несколько типов данных:
UL (Unsigned Long) — 4-х байтовое целое беззначное число.
На PHP это выглядит так:
$data = pack('L1',$int);
LPS (Long-Prefixed String) — строки с префиксированной длиной (в виде UL).
На PHP это выглядит так:
$data = pack('L1',strlen($string)).$string;
Z (Zero-endian) — сроки без префиксированной длины, с нулевым байтом в конце (\0).
В текущей версии протокола не используются, однако могут использоваться при обработке серверного списка контактов.
UIDL (Unique ID Listing) — строка длиной в 8 байт, состоящая из любых символов. Используется для идентификации сообщений.
Выражения:
Пустой LPS — LPS с пустой строкой. Т.е. UL, равный нулю.
string — строка без префиксированной длины (предполагается, что длина была указана раньше или заведомо известна)
От себя:
Не понимаю, зачем префиксировать длину строки, используя 4-х байтовое число. 2-х байтовое число (макс. 65535) было бы вполне достаточно (хотя, и это много).
Заголовок любого пакета при работе с MRIM сервером выглядит таким образом:
UL — «магический ключ», указывающий на то, что мы работаем именно с MRIM протоколом. Сейчас равен 0xDEADBEEF.
UL — версия протокола. Сейчас равен 0x010013.
UL — номер пакета (последовательность пакета). Нумерация начинается с нуля и с каждым отправляемым пакетом увеличивается на 1. Когда доходит до своего максимума — 0xFFFFFFFF, вновь сбрасывается в ноль.
UL — идентификатор команды.
UL — длина данных в пакете.
UL — IP в формате INET_ATON (можно передавать 0)
UL — порт (можно передавать 0)
ULx4 — 4 зарезервированных UL для дальнейшего расширения протокола. При отправке пакетов заполняются нулями.
string — данные пакета. Длина этой строки указана в 5-м UL.
Функция для генерации пакетов выглядит таким образом:
function make_packet($msg,$data = '') { $dlen = ($data?strlen($data):0); $mrim_packet = pack('L*',$this->CS_MAGIC,$this->PROTO_VERSION,$this->mnumb,$msg,$dlen,0,0,0,0,0,0); if($data) $mrim_packet .= $data; if($this->mnumb == 0xFFFFFFFF) $this->mnumb = 0; else $this->mnumb++; return $mrim_packet; }
Константы протокола:
var $CS_MAGIC = 0xDEADBEEF; var $PROTO_VERSION = 0x00010013; var $CONTACT_FLAG_GROUP = 0x02; var $CONTACT_FLAG_IGNORE = 0x10; var $CONTACT_FLAG_INVISIBLE = 0x04; var $CONTACT_FLAG_REMOVED = 0x01; var $CONTACT_FLAG_SHADOW = 0x20; var $CONTACT_FLAG_SMS = 0x100000; var $CONTACT_FLAG_VISIBLE = 0x08; var $CONTACT_INTFLAG_NOT_AUTHORIZED = 0x01; var $CONTACT_OPER_ERROR = 0x01; var $CONTACT_OPER_GROUP_LIMIT = 0x6; var $CONTACT_OPER_INTERR = 0x02; var $CONTACT_OPER_INVALID_INFO = 0x04; var $CONTACT_OPER_NO_SUCH_USER = 0x03; var $CONTACT_OPER_SUCCESS = 0x00; var $CONTACT_OPER_USER_EXISTS = 0x05; var $FILE_TRANSFER_MIRROR = 4; var $FILE_TRANSFER_STATUS_DECLINE = 0; var $FILE_TRANSFER_STATUS_ERROR = 2; var $FILE_TRANSFER_STATUS_INCOMPATIBLE_VERS = 3; var $FILE_TRANSFER_STATUS_OK = 1; var $GET_CONTACTS_ERROR = 0x01; var $GET_CONTACTS_INTERR = 0x02; var $GET_CONTACTS_OK = 0x00; var $LOGOUT_NO_RELOGIN_FLAG = 0x10; var $MAX_CLIENT_DESCRIPTION = 256; var $MESSAGE_DELIVERED = 0x00; var $MESSAGE_FLAG_ALARM = 0x4000; var $MESSAGE_FLAG_AUTHORIZE = 0x08; var $MESSAGE_FLAG_CONTACT = 0x0200; var $MESSAGE_FLAG_MULTICAST = 0x1000; var $MESSAGE_FLAG_NORECV = 0x04; var $MESSAGE_FLAG_NOTIFY = 0x0400; var $MESSAGE_FLAG_OFFLINE = 0x01; var $MESSAGE_FLAG_OLD = 0x200000; var $MESSAGE_FLAG_RTF = 0x80; var $MESSAGE_FLAG_SMS = 0x0800; var $MESSAGE_FLAG_SMS_NOTIFY = 0x2000; var $MESSAGE_FLAG_SPAM = 0x010000; var $MESSAGE_FLAG_SYSTEM = 0x40; var $MESSAGE_FLAG_UNI = 0x100000; var $MESSAGE_REJECTED_DENY_OFFMSG = 0x8006; var $MESSAGE_REJECTED_INTERR = 0x8003; var $MESSAGE_REJECTED_LIMIT_EXCEEDED = 0x8004; var $MESSAGE_REJECTED_NOUSER = 0x8001; var $MESSAGE_REJECTED_TOO_LARGE = 0x8005; var $MESSAGE_USERFLAGS_MASK = 0x36A8; var $MRIM_ANKETA_INFO_STATUS_DBERR = 2; var $MRIM_ANKETA_INFO_STATUS_NOUSER = 0; var $MRIM_ANKETA_INFO_STATUS_OK = 1; var $MRIM_ANKETA_INFO_STATUS_RATELIMERR = 3; var $MRIM_CS_ADD_CONTACT = 0x1019; var $MRIM_CS_ADD_CONTACT_ACK = 0x101A; var $MRIM_CS_ANKETA_INFO = 0x1028; var $MRIM_CS_AUTHORIZE = 0x1020; var $MRIM_CS_AUTHORIZE_ACK = 0x1021; var $MRIM_CS_CHANGE_STATUS = 0x1022; var $MRIM_CS_CONNECTION_PARAMS = 0x1014; var $MRIM_CS_CONTACT_LIST2 = 0x1037; var $MRIM_CS_DELETE_OFFLINE_MESSAGE = 0x101E; var $MRIM_CS_FILE_TRANSFER = 0x1026; var $MRIM_CS_FILE_TRANSFER_ACK = 0x1027; var $MRIM_CS_GET_MPOP_SESSION = 0x1024; var $MRIM_CS_HELLO = 0x1001; var $MRIM_CS_HELLO_ACK = 0x1002; var $MRIM_CS_LOGIN_ACK = 0x1004; var $MRIM_CS_LOGIN_REJ = 0x1005; var $MRIM_CS_LOGIN2 = 0x1038; var $MRIM_CS_LOGOUT = 0x1013; var $MRIM_CS_MAILBOX_STATUS = 0x1033; var $MRIM_CS_MESSAGE = 0x1008; var $MRIM_CS_MESSAGE_ACK = 0x1009; var $MRIM_CS_MESSAGE_RECV = 0x1011; var $MRIM_CS_MESSAGE_STATUS = 0x1012; var $MRIM_CS_MODIFY_CONTACT = 0x101B; var $MRIM_CS_MODIFY_CONTACT_ACK = 0x101C; var $MRIM_CS_MPOP_SESSION = 0x1025; var $MRIM_CS_NEW_EMAIL = 0x1048; var $MRIM_CS_OFFLINE_MESSAGE_ACK = 0x101D; var $MRIM_CS_PING = 0x1006; var $MRIM_CS_SMS = 0x1039; var $MRIM_CS_SMS_ACK = 0x1040; var $MRIM_CS_USER_INFO = 0x1015; var $MRIM_CS_USER_STATUS = 0x100F; var $MRIM_CS_WP_REQUEST = 0x1029; var $MRIM_CS_WP_REQUEST_PARAM_BIRTHDAY = 6; var $MRIM_CS_WP_REQUEST_PARAM_BIRTHDAY_DAY = 14; var $MRIM_CS_WP_REQUEST_PARAM_BIRTHDAY_MONTH = 13; var $MRIM_CS_WP_REQUEST_PARAM_CITY_ID = 11; var $MRIM_CS_WP_REQUEST_PARAM_COUNTRY_ID = 15; var $MRIM_CS_WP_REQUEST_PARAM_DATE1 = 7; var $MRIM_CS_WP_REQUEST_PARAM_DATE2 = 8; var $MRIM_CS_WP_REQUEST_PARAM_DOMAIN = 1; var $MRIM_CS_WP_REQUEST_PARAM_FIRSTNAME = 3; var $MRIM_CS_WP_REQUEST_PARAM_LASTNAME = 4; var $MRIM_CS_WP_REQUEST_PARAM_MAX = 16; var $MRIM_CS_WP_REQUEST_PARAM_NICKNAME = 2; var $MRIM_CS_WP_REQUEST_PARAM_ONLINE = 9; var $MRIM_CS_WP_REQUEST_PARAM_SEX = 5; var $MRIM_CS_WP_REQUEST_PARAM_STATUS = 10; var $MRIM_CS_WP_REQUEST_PARAM_USER = 0; var $MRIM_CS_WP_REQUEST_PARAM_ZODIAC = 12; var $MRIM_GET_SESSION_FAIL = 0; var $MRIM_GET_SESSION_SUCCESS = 1; var $PARAM_VALUE_LENGTH_LIMIT = 64; var $PARAMS_NUMBER_LIMIT = 50; var $SMS_ACK_DELIVERY_STATUS_INVALID_PARAMS = 0x10000; var $SMS_ACK_DELIVERY_STATUS_SUCCESS = 1; var $SMS_ACK_SERVICE_UNAVAILABLE = 2; var $STATUS_AWAY = 0x02; var $STATUS_FLAG_INVISIBLE = 0x80000000; var $STATUS_OFFLINE = 0x00; var $STATUS_ONLINE = 0x01; var $STATUS_OTHER = 0x04; var $STATUS_UNDETERMINATED = 0x03;
При приёме пакета мы должны в начале прочитать 44 байта (т.е. заголовок пакета):
$answ = fread($this->sock,44);
Затем, парсим информацию из заголовка. Нас интересует длина данных в пакете.
list(,$magic,$proto,$seq,$msg,$dlen,$from,$fromport,$r1,$r2,$r3,$r4) = unpack('L*',$answ);
Проверяем, если $dlen больше нуля и читаем данные пакета (без проверки на ноль fread выдаст Warning, если в пакете нет данных. Нам оно нужно?):
$a = fread($this->sock,$dlen);
После подключения мы должны серверу отправить такой пакет:
Идентификатор команды равен MRIM_CS_HELLO.
В качестве ответа мы должны получить пакет, в данных которого один UL — время пинга. После этого мы должны посылать серверу пакет «PING» один раз в указанный здесь промежуток.
Пакет «PING»:
Идентификатор команды равен MRIM_CS_PING.
Данных в пакете нет.
Авторизация на сервере:
При авторизации логин и пароль передаются на сервер открытым текстом. Безопасный вход в протоколе пока не предусмотрен.
Пакет выглядит следующим образом:
Идентификатор команды равен MRIM_CS_LOGIN2.
LPS — логин (адрес почты)
LPS — пароль
UL — статус (при установке статуса «невидим» необходимо объединить флаги таким образом: $this->STATUS_ONLINE | $this->STATUS_FLAG_INVISIBLE
при установке «нестандартного» статуса используется флаг STATUS_OTHER)
LPS — название статуса (STATUS_ONLINE, STATUS_INVISIBLE, STATUS_AWAY, status_*) (где * — идентификатор дополнительного статуса, т.е. любое число или слово)
LPS — заголовок икс-статуса в кодировке UTF-16LE
LPS — текст икс-статуса в кодировке UTF-16LE
UL — неизвестный мне параметр. Равен 0x03FF. (Предположительно, служит для скрытия/отображения названия/версии клиента. Второе значение, которое я встречал — это 0xFFFFFFFF.)
LPS — описание клиента в таком формате: client=«название» version=«версия» build=«сборка»
LPS — язык клиента (стандартно — ru)
LPS — строка с кратким описанием клиента (в произвольном формате)
В качестве ответа мы должны получить идентификатор команды (далее — MSG) равным MRIM_CS_LOGIN_ACK. В противном случае, вход невозможен (вероятно, неверный пароль или аккаунт временно заблокирован)
Пакеты, отправляемые на сервер:
Отправка сообщения:
Возможна отправка сообщений нескольких типов. Все тексты сообщений в кодировке UTF-16LE. Пакет при этом выглядит таким образом:
MSG равен MRIM_CS_MESSAGE.
UL — флаги (тип) сообщения.
LPS — адрес, кому адресовано сообщение.
LPS — текстовая версия сообщения.
LPS — RTF версия сообщения в таком формате: base64_encode(gzcompress(UL — количество LPS (2), LPS — RTF текст со всеми заголовками, LPS — цвет фона в виде UL (т.е. UL внутри LPS, такой вот маразм)))
При отправке простых сообщений RTF версию можно не передавать. (флаг равен 0, MESSAGE_FLAG_OFFLINE или MESSAGE_FLAG_RTF при наличии RTF версии сообщения)
При отправке запроса авторизации текст должен указываться в таком формате: base64_encode(UL — количество LPS (2), LPS — мой ник в кодировке UTF-16LE, LPS — текст запроса авторизации), RTF версия может быть пустой. Флаг равен MESSAGE_FLAG_AUTHORIZE.
При отправке уведомления «вам печатают» текст и весь LPS с RTF версией должны состоять из одного пробела. Флаг равен MESSAGE_FLAG_NOTIFY.
При отправке «будильника» должны быть указаны и текстовая, и RTF версии сообщения (альтернатива, которую увидит собеседник, если его клиент не поддерживает «будильник»). Флаг равен паре MESSAGE_FLAG_ALARM и MESSAGE_FLAG_RTF ($this->MESSAGE_FLAG_ALARM | $this->MESSAGE_FLAG_RTF).
При отправке списка контактов, текстовая версия предоставляется в формате имя1; адрес1; имя2; адрес2;..., а LPS RTF версии должен состоять из одного пробела. Всё тело текстовой версии передаётся в UTF-16LE. Флаг равен MESSAGE_FLAG_CONTACT)
От себя:
Брррр. Ну и намутили они с RTF версией сообщения.
Отправка SMS сообщений:
MSG равен MRIM_CS_SMS.
UL — неизвестный параметр. Равен нулю.
LPS — номер телефона в международном формате, на который должно быть доставлено сообщение.
LPS — текст сообщения в кодировке UTF-16LE.
Примечание: контакт с этим номером телефона должен быть в списке (как обычный или как SMS контакт).
Одобрение авторизации:
MSG равен MRIM_CS_AUTHORIZE.
LPS — адрес запросившего авторизацию.
Установка нового статуса:
MSG равен MRIM_CS_CHANGE_STATUS.
UL — статус (при установке статуса «невидим» необходимо объединить флаги таким образом: $this->STATUS_ONLINE | $this->STATUS_FLAG_INVISIBLE
при установке «нестандартного» статуса используется флаг STATUS_OTHER)
LPS — название статуса (STATUS_ONLINE, STATUS_INVISIBLE, STATUS_AWAY, status_*) (где * — идентификатор дополнительного статуса, т.е. любое число или слово)
LPS — заголовок икс-статуса в кодировке UTF-16LE
LPS — текст икс-статуса в кодировке UTF-16LE
UL — неизвестный мне параметр. Равен 0x03FF. (Предположительно, служит для скрытия/отображения названия/версии клиента. Второе значение, которое я встречал — это 0xFFFFFFFF.)
Добавление нового контакта в список:
MSG равен MRIM_CS_ADD_CONTACT.
UL — флаги.
UL — номер (ID) группы (можно получить из списка контактов)
LPS — адрес добавляемого контакта.
LPS — имя (ник) добавляемого контакта в кодировке UTF-16LE.
LPS — номер телефона добавляемого контакта в международном формате.
LPS — текстовая версия запроса авторизации в формате: base64_encode(UL — количество LPS (2), LPS — мой ник в кодировке UTF-16LE, LPS — текст запроса авторизации в кодировке UTF-16LE)
LPS — предположительно, RTF версия запроса авторизации. Отправляется пустой LPS.
Флаги:
CONTACT_FLAG_INVISIBLE — Контакт должен попасть в список «Я всегда невидим для»
CONTACT_FLAG_VISIBLE — Контакт должен попасть в список «Я всегда видим для»
CONTACT_FLAG_IGNORE — Контакт должен попасть в список игнорируемых
CONTACT_FLAG_SHADOW — Контакт не должен попасть в основной контакт-лист (применяется в паре с одним из трех предыдущих)
CONTACT_FLAG_REMOVED — Контакт удален
CONTACT_FLAG_SMS — Добавляется SMS контакт. При этом адрес равен строке «phone», а ID группы равен 0x67.
Добавление новой группы в список контактов:
MSG равен MRIM_CS_ADD_CONTACT.
UL — флаги (равен CONTACT_FLAG_GROUP).
UL — равен 0.
LPS — пустой LPS.
LPS — имя добавляемой группы в кодировке UTF-16LE.
LPS — текстовая версия запроса авторизации в формате: base64_encode(UL — количество LPS (2), LPS — мой ник в кодировке UTF-16LE, LPS — текст запроса авторизации в кодировке UTF-16LE)
LPS — предположительно, RTF версия запроса авторизации. Отправляется пустой LPS.
От себя:
Не понятно, зачем нужно передавать текст запроса авторизации при добавлении группы? Предполагаю, что два последних LPS могут быть пустыми.
Изменение контакта в списке:
MSG равен MRIM_CS_MODIFY_CONTACT.
UL — ID контакта (можно получить из списка контактов)
UL — флаги.
UL — номер (ID) группы (можно получить из списка контактов), используется для перемещения контакта в другую группу.
LPS — адрес контакта.
LPS — имя (ник) контакта в кодировке UTF-16LE.
LPS — номер телефона контакта в международном формате.
Флаги:
CONTACT_FLAG_INVISIBLE — Контакт должен попасть в список «Я всегда невидим для»
CONTACT_FLAG_VISIBLE — Контакт должен попасть в список «Я всегда видим для»
CONTACT_FLAG_IGNORE — Контакт должен попасть в список игнорируемых
CONTACT_FLAG_SHADOW — Контакт не должен попасть в основной контакт-лист (применяется в паре с одним из трех предыдущих)
CONTACT_FLAG_REMOVED — Контакт удален
CONTACT_FLAG_SMS — SMS контакт. При этом адрес равен строке «phone», а ID группы равен 0x67.
Изменение группы в списке:
MSG равен MRIM_CS_MODIFY_CONTACT.
UL — ID группы (можно получить из списка контактов)
UL — флаги.
UL — равен 0.
LPS — пустой LPS.
LPS — имя группы в кодировке UTF-16LE.
LPS — пустой LPS.
Флаги:
Используется CONTACT_FLAG_GROUP вместе со следующими флагами:
CONTACT_FLAG_SHADOW — Группа не должна попасть в основной контакт-лист
CONTACT_FLAG_REMOVED — Группа удалена
Поиск контакта в базе Mail.Ru:
MSG равен MRIM_CS_WP_REQUEST.
string — данные запроса, состоящие из блоков. Длина не префиксируется.
Каждый блок выглядит следующим образом:
UL — параметр поиска.
LPS — значение параметра.
Допустимые параметры со значениями:
Ник, имя и фамилия указываются в кодировке UTF-16LE.
MRIM_CS_WP_REQUEST_PARAM_USER — логин (без домена), обязан комбинироваться с доменом
MRIM_CS_WP_REQUEST_PARAM_DOMAIN — почтовый домен
MRIM_CS_WP_REQUEST_PARAM_NICKNAME — ник
MRIM_CS_WP_REQUEST_PARAM_FIRSTNAME — имя
MRIM_CS_WP_REQUEST_PARAM_LASTNAME — фамилия, * в конце ника/имени/фамилии указывает на возможность любого продолжения имени
MRIM_CS_WP_REQUEST_PARAM_SEX — пол. 1 — мужской, 2 — женский
MRIM_CS_WP_REQUEST_PARAM_DATE1 — минимальный возраст (в годах)
MRIM_CS_WP_REQUEST_PARAM_DATE2 — максимальный возраст (в годах)
MRIM_CS_WP_REQUEST_PARAM_CITY_ID — ID региона проживания
MRIM_CS_WP_REQUEST_PARAM_ZODIAC — Знак зодиака (Овен — 1, ..., Рыбы — 12)
MRIM_CS_WP_REQUEST_PARAM_BIRTHDAY_MONTH — Месяц рождения (Январь — 1, ..., Декабрь — 12)
MRIM_CS_WP_REQUEST_PARAM_BIRTHDAY_DAY — День рождения (обязан комбинироваться с месяцем рождения)
MRIM_CS_WP_REQUEST_PARAM_COUNTRY_ID — ID страны проживания
MRIM_CS_WP_REQUEST_PARAM_ONLINE — ищем ли мы только подключенных в данный момент пользователей (1 — единственное возможное значение)
Параметры могут использоваться в любых комбинациях (кроме случаев, когда один параметр обязан комбинироваться с другим), в любом порядке и должны соединяться в общую строку string.
Требование ключа для web-авторизации:
MSG равен MRIM_CS_GET_MPOP_SESSION.
Данных в пакете нет.
Используется для входа в почтовый ящик Mail.Ru без дополнительной авторизации и не передавая свой пароль в GET-запросе.
Пакеты, принимаемые от сервера:
Информация о пользователе (собственная информация):
MSG равен MRIM_CS_USER_INFO.
string — данные без префиксированной длины.
Данные передаются в виде последовательности LPS. Причём, нечётные LPS — названия параметров, а соотв. чётные — значения параметров.
Основные параметры:
MESSAGES.TOTAL — количество писем в ящике
MESSAGES.UNREAD — количество непрочитанных писем в ящике
MRIM.NICKNAME — ник пользователя
client.endpoint — до конца не ясный параметр. В нём указывается наш IP (с которого мы подключились к серверу) и порт.
Статус пользователя:
Используется сервером для сообщения нам нового статуса одного из наших контактов.
MSG равен MRIM_CS_USER_STATUS.
UL — статус.
LPS — название статуса (STATUS_ONLINE, STATUS_INVISIBLE, STATUS_AWAY, status_*) (где * — идентификатор дополнительного статуса, т.е. любое число или слово)
LPS — заголовок икс-статуса в кодировке UTF-16LE
LPS — текст икс-статуса в кодировке UTF-16LE
LPS — адрес контакта.
UL — неизвестный мне параметр. Равен 0x03FF. (Предположительно, служит для скрытия/отображения названия/версии клиента. Второе значение, которое я встречал — это 0xFFFFFFFF.)
Ключ для WEB авторизации:
MSG равен MRIM_CS_MPOP_SESSION.
UL — статус.
LPS — ключ.
Если статус равен MRIM_GET_SESSION_SUCCESS, в последующем LPS будет содержаться ключ, который можно использовать для входа в почтовый ящик.
Для входа в ящик можно использовать URL:win.mail.ru/cgi-bin/auth?Login=адрес&∓agent=ключ
Количество писем в почтовом ящике:
MSG равен MRIM_CS_MAILBOX_STATUS.
UL — количество непрочитанных писем в ящике.
Используется сервером для уведомления об изменении количества непрочитанных писем в ящике (приход новой почты или удаление/прочтение писем).
Уведомление о приходе нового письма:
MSG равен MRIM_CS_NEW_EMAIL.
UL — количество непрочитанных писем в ящике.
LPS — адрес, от кого получено письмо (в RFC формате в кодировке UTF-16LE)
LPS — тема письма в кодировке UTF-16LE.
Входящее сообщение:
MSG равен MRIM_CS_MESSAGE_ACK.
UL — sequence (последовательность) этого сообщения для отправителя.
UL — флаги сообщения.
LPS — адрес отправителя сообщения.
LPS — текстовая версия сообщения.
LPS — RTF версия сообщения.
Форматы и флаги аналогичны используемым при отправке сообщений, однако при наличии флага MESSAGE_FLAG_OLD, текст сообщения передаётся в кодировке Windows-1251.
При приёме сообщения необходимо послать пакет с MSG равным MRIM_CS_MESSAGE_RECV и данными следующего вида:
LPS — адрес, от кого получено сообщение.
UL — sequence сообщения.
Естественно, НЕ НУЖНО отправлять этот пакет, если у нас статус «невидим». В противном случае будет возможна такая проверка на невидимость.
Изменение параметров соединения:
MSG равен MRIM_CS_CONNECTION_PARAMS.
UL — новый интервал для отправки пакетов «PING».
При этом ближайший PING должен отправляться уже с учётом нового интервала.
Сообщение о разрыве соединения:
MSG равен MRIM_CS_LOGOUT.
UL — причина разрыва.
Если в причине указан флаг LOGOUT_NO_RELOGIN_FLAG, это значит, что агент с данной учётной записью был открыт на другом компьютере.
Уведомление об одобрении авторизации:
MSG равен MRIM_CS_AUTHORIZE_ACK.
LPS — адрес одобрившего авторизацию.
Входящее оффлайн сообщение:
MSG равен MRIM_CS_OFFLINE_MESSAGE_ACK.
UIDL — ID сообщения.
LPS — текст сообщения со всеми заголовками в RFC-822 формате.
При этом заголовок From содержит адрес отправитела, Date — дату отправки сообщения, X-Mrim-Flags — флаги сообщения (в шестнадцатеричном виде).
Boundary для разделения текстовой и RTF частей может содержаться в заголовке Boundary (хоть это и противоречит RFC) либо в Content-Type.
Флаги сообщения такие же, как при приёме обычного сообщения. Content-Type равный application/x-mrim-auth-req явно указывает на то, что сообщение является запросом авторизации.
Content-Type начинающийся с multipart/ указывает на то, что сообщение содержит RTF часть.
Кодировка сообщения может явно указываться в Content-Type, а может и не указываться.
В таком случае необходимо проверить флаги на наличие MESSAGE_FLAG_OLD и при его наличии рассматривать сообщение в кодировке Windows-1251. В противном случае — кодировка сообщения UTF-16LE.
Content-Transfer-Encoding указывает на метод кодирования сообщения (base64, quoted-printable и т.п.)
Сообщение было отправлено, пока мы находились не в сети.
От себя:
Да уж… Перемудрили с RFC здесь. Гораздо разумнее было бы использовать UL/LPS для передачи сообщения...
Список контактов:
MSG равен MRIM_CS_CONTACT_LIST2.
Типы данных в масках:
u — UL
s — LPS
z — Z (сейчас не используется)
Данные пакета:
UL — статус получения списка контактов (GET_CONTACTS_OK — ОК, GET_CONTACTS_ERROR — ошибка базы данных на сервере, GET_CONTACTS_INTERR — внутренняя ошибка)
UL — количество групп в списке.
LPS — описание маски списка групп (каждый символ указывает на определённый тип данных)
LPS — определение маски списка контактов (каждый символ указывает на определённый тип данных)
string — список групп (количество групп и маска описания указаны во втором и третьем параметре)
string — список контактов.
Порядок нумерации ID групп начинается с нуля.
Порядок нумерации ID контактов начинается с 20.
Описание групп сейчас состоит из двух параметров (us):
UL — флаги группы.
LPS — имя группы в кодировке UTF-16LE.
При наличии других параметров, данные должны быть прочитаны и проигнорированы.
Описание контактов сейчас состоит из 12 параметров (uussuussssus):
UL — флаги контакта.
UL — ID группы.
LPS — адрес контакта.
LPS — имя (ник) контакта в кодировке UTF-16LE.
UL — серверные флаги (CONTACT_INTFLAG_NOT_AUTHORIZED — контакт не авторизован)
UL — статус.
LPS — номер телефона в международном формате.
LPS — название статуса.
LPS — заголовок икс-статуса в кодировке UTF-16LE.
LPS — текст икс-статуса в кодировке UTF-16LE.
UL — неизвестный мне параметр. Равен 0x03FF. (Предположительно, служит для скрытия/отображения названия/версии клиента. Второе значение, которое я встречал — это 0xFFFFFFFF.)
LPS — описание клиента в таком формате: client=«название» version=«версия» build=«сборка»
При обновлении протокола могут добавляться новые параметры, но порядок старых не будет меняться (во всяком случае, так заявлено на mail.ru)
Результат добавления контакта (группы):
MSG равен MRIM_CS_ADD_CONTACT_ACK.
UL — результат операции.
UL — присвоенный новому контакту номер (ID)
Возможные результаты:
CONTACT_OPER_SUCCESS — добавление произведено успешно
CONTACT_OPER_ERROR — переданные данные были некорректны
CONTACT_OPER_INTERR — при обработке запроса произошла внутренняя ошибка
CONTACT_OPER_NO_SUCH_USER — добавляемого пользователя не существует в системе
CONTACT_OPER_INVALID_INFO — некорректное имя пользователя
CONTACT_OPER_USER_EXISTS — пользователь уже есть в контакт-листе
CONTACT_OPER_GROUP_LIMIT — превышено максимально допустимое количество групп (20)
Результат изменения контакта:
MSG равен MRIM_CS_MODIFY_CONTACT_ACK.
UL — результат операции (может принимать те же значения, что и при получении результата добавления контакта.
Отчёт о доставке SMS сообщения:
MSG равен MRIM_CS_SMS_ACK.
UL — статус доставки.
Статусы:
SMS_ACK_DELIVERY_STATUS_INVALID_PARAMS — неверные параметры запроса на отправку.
SMS_ACK_SERVICE_UNAVAILABLE — сервис недоступен.
SMS_ACK_DELIVERY_STATUS_SUCCESS — сообщение отправлено.
Список найденных пользователей:
MSG равен MRIM_CS_ANKETA_INFO.
UL — результат операции.
UL — количество полей в анкете каждого пользователя (N).
UL — текущее ограничение на количество результатов поиска (может быть больше, чем количество строк в данном ответе) (при следующем∓ запросе на поиск с такими же параметрами будет показана следующая страница)
UL — текущее серверное время (timestamp).
LPSxN — N LPS с названиями полей.
Далее идут LPS со значениями полей анкеты для каждого найденного по запросу пользователя в том же порядке, что в списке полей, по N штук на каждого.
Возможные результаты:
MRIM_ANKETA_INFO_STATUS_OK — поиск успешно завершен
MRIM_ANKETA_INFO_STATUS_NOUSER — не найдено ни одной подходящей записи
MRIM_ANKETA_INFO_STATUS_RATELIMERR — слишком много запросов, поиск временно запрещен
Формирование ссылок на проекты Мой Мир, Фото, Видео, Блоги:
Для проекта «Мой Мир»: r.mail.ru/cln3587/my.mail.ru/домен/логин/
Для проекта «Фото»: r.mail.ru/cln3565/foto.mail.ru/домен/логин/
Для проекта «Видео»: r.mail.ru/cln3567/video.mail.ru/домен/логин/
Для проекта «Блоги»: r.mail.ru/cln3566/blogs.mail.ru/домен/логин/
Загрузка фотографий (аватар):
Малое фото: obraz.foto.mail.ru/домен/логин/_mrimavatarsmall
Большое фото: obraz.foto.mail.ru/домен/логин/_mrimavatar
В качестве домена указывается часть до первого вхождения точки. То есть:
mail.ru => mail
bk.ru => bk
list.ru => list
inbox.ru => inbox
corp.mail.ru => corp
Автор статьи Eugen.
Любое (полное или частичное) копирование материалов не приветствуется.