Архитектура современных почтовых систем


Знание основ освобождает от необходимости запоминать тысячи фактов. Попробуем подойти к построению почтовой системы, опираясь на этот принцип, и сделаем акцент не на настройку компонентов почтового сервера (об этом и так достаточно написано), а на взаимосвязь между компонентами и на протоколы, по которым они общаются между собой.


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


Для того, чтобы упростить задачу, мы откажемся от рассмотрения таких монстров, как Microsoft Exchange или Lotus Notes/Domino , и сосредоточим внимание на открытом программном обеспечении и стандартных почтовых протоколах - их в большинстве случаев более, чем достаточно. Не будем мы рассматривать и протокол UUCP - многие из тех, кто знал, что это такое, уже успели про него забыть.

Взгляд с высоты птичьего полета


Главной отличительной чертой почтовой системы, построенной на открытом программном обеспечении, является ее модульность. Отдельные компоненты являются взаимозаменяемыми, для каждого компонента существует несколько реализаций. Замена компонентов, предназначенных для одной цели, в большинстве случаев катастрофой не является: базовая функциональность заменяемых компонентов в целом одинакова, настройки и данные тоже, как правило, можно перенести, а иногда даже использовать без изменения.


Принципиальная схема работы электронной почты и способы взаимодействия между ее основными компонентами представлены на следующем изображении:

Как создаются почтовые сообщения


С точки зрения пользователя почтовой системы существует только один компонент - это MUA (Mail User Agent), или, другими словами, его почтовый клиент (Mozilla, Outlook, The Bat!, KMail, mutt, pine, mailx, а также Web-приложения аналогичного назначения), предназначенный для создания, отправки, получения и чтения почтовых сообщений.


Формат почтовых сообщений описан в RFC 2822 ( Internet Message Format ) и в серии RFC с 2045 по 2049, которые посвящены формату MIME - Multipurpose Internet Mail Extensions (Format of Internet Message Bodies, Media Types, Message Header Extensions for Non-ASCII Text, Registration Procedures, Conformance Criteria and Examples).


Если коротко, то любое почтовое сообщение состоит из заголовков и тела, разделенных пустой строкой. Каждый заголовок, в свою очередь, состоит из имени и значения, разделенных двоеточием.


Следующие заголовки считаются обязательными:

  • From - адрес и, возможно, полное имя отправителя
  • To - адрес и, возможно, полное имя того, кому адресовано письмо (адресатов может быть несколько)
  • Subject - тема письма
  • Date - локальные дата и время отправления письма


Другими часто используемыми заголовками являются:

  • Сс (carbon copy) - кому отправить копию письма (адресатов может быть несколько), при этом и основному адресату, и дополнительным, будет об этом известно
  • Received - путь прохождения письма
  • Content-Type - информация о том, каким образом письмо должно быть отображено


Многие MUA позволяют указать заголовок Bcc (Blind carbon copy) - его получатели письма не увидят никогда. Получатели, упомянутые в To и Cc, ничего не узнают о получателях, упомянутых в Bcc, а последние ничего не узнают друг о друге, но, тем не менее, они получат письмо и будут недоумевать: как в их почтовом ящике оказалось сообщение, в числе адресатов которого они не упомянуты? Этот заголовок используется преимущественно спамерами.


Имена заголовков могут содержать только 7-битные ASCII-символы. Значения заголовков не ограничены символами ASCII, но при наличии не ASCII-символов они должны использовать MIME-кодирование в форме »=?charset?encoding?encoded text?=».


Существуют следующие типы кодирования:

  • 7bit - до 998 октетов на строку из диапазона [1..127]\{CR, LF}. Используется по умолчанию.
  • quoted-printable - используется в первую очередь для US-ASCII-символов, но также содержит символы из других диапазонов.
  • base64 - используется для двоичных данных.
  • 8bit - до 998 октетов на строку из диапазона [1..255]\{CR, LF}. Этот тип кодирования в заголовках почтовых сообщений использовать нежелательно, о причинах мы поговорим позже.
  • binary - произвольная последовательность октетов (фактически отсутствие какого бы то ни было кодирования). Этот тип кодирования использовать нельзя.


Таким же точно образом кодируется тело письма, при этом кодировка и тип кодирования указывается в заголовках Content-Type и Content-Transfer-Encoding. Вот пример типичного почтового сообщения:

Message-ID: <436F19FC.7050901@mail.domain1.com>
Date: Mon, 07 Nov 2005 12:10:20 +0300
From: User 1 <user1@domain1.com>
User-Agent: Mozilla Thunderbird 0.6 (X11/20040511)
X-Accept-Language: en-us, en
MIME-Version: 1.0
To:  user2@domain2.com
Subject: =?KOI8-R?Q?=F4=C5=D3=D4?=
Content-Type: text/plain; charset=KOI8-R; format=flowed
Content-Transfer-Encoding: 8bit

Привет!


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

Message-ID: <436F2097.5060703@mail.domain1.com>
Date: Mon, 07 Nov 2005 12:38:31 +0300
From: User 1 <user1@domain1.com>
User-Agent: Mozilla Thunderbird 0.6 (X11/20040511)
X-Accept-Language: en-us, en
MIME-Version: 1.0
To:  user2@domain2.com
Subject: =?KOI8-R?Q?=F4=C5=D3=D4?=
Content-Type: multipart/mixed;
 boundary="------------070102080309020306010600"

This is a multi-part message in MIME format.
--------------070102080309020306010600
Content-Type: text/plain; charset=KOI8-R; format=flowed
Content-Transfer-Encoding: 8bit

Привет!


--------------070102080309020306010600
Content-Type: text/plain;
 name="file.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="file.txt"

Text file content

--------------070102080309020306010600--

Как происходит отправка почтовых сообщений


После создания сообщения MUA должен передать его MSA (Mail Submission Agent). В RFC 2476 ( Message Submission ) MSA описан как сервис, принимающий клиентские подключения на порту 678 по TCP/IP, и выполняющий первичную проверку почтовых сообщений на соответствие стандартам, авторизацию пользователей и блокирование UCE (Unsolicited Commercial Email - мы привыкли обозначать эту корреспонденцию словом «спам») еще на этапе отправки. Затем MSA должен передать письмо MTA (Mail Transfer Agent) - сервису, принимающему клиентские подключения на порту 25 по TCP/IP, который, в свою очередь, уже должен заняться доставкой письма непосредственно адресату. И в первом, и во втором случае должен использоваться протокол SMTP, описанный в RFC 2821 ( Simple Mail Transfer Protocol ) и RFC 1869 ( SMTP Service Extensions ), но MUA и MTA не должны общаться напрямую друг с другом.


На практике отдельных реализаций MSA не существует, а большинство реализаций MTA способны также выполнять функции MSA. Более того, для MSA практически никогда не конфигурируется порт 678, а все почтовые сообщения от MUA принимаются непосредственно на порт 25.


Поведение MTA после того, как он получил почтовое сообщение от MUA или MSA, зависит от настроек самого MTA, а также от домена, которому принадлежит почтовый адрес получателя. В простейшем случае (в отсутствии постоянного подключения к Интернет, постоянного реального ip-адреса и dns-имени - в сегодняшних реалиях такое происходит довольно редко) MTA вообще не берет на себя ответственность за пересылку письма, а просто отдает ее вышестоящему MTA, который для него является релеем (relay - MTA, через который производится пересылка). Релей может определить список сетей/хостов и/или список логинов/паролей, которым разрешено пересылать через него свои почтовые сообщения. Домены, обслуживаемые релеем, как правило, являются исключением: для них сообщения принимаются от кого угодно.


Релей, не устанавливающий никаких ограничений на пересылку почтовых сообщений, называется открытым релеем (open relay). Все открытые релеи ждет одна и та же участь:

  • Сначала их услугами начинают активно пользоваться спаммеры
  • Затем релей попадает в какой-либо черный список, и все MTA, выполняющие фильтрацию по черным спискам (а их сейчас большинство), перестают принимать от него почтовые сообщения


МТА, принимающий на себя ответственность за пересылку, сначала проверяет, обслуживает ли он домен адресата. В случае отрицательного решения MTA предпринимает попытку найти другой MTA, обслуживающий этот домен. Для этого он с помощью DNS-запроса получает список MX-записей домена, каждая из которых содержит приоритет в виде целого числа - чем оно меньше, тем MTA «главнее». В первую очередь предпринимается попытка отправить почтовое сообщение на главный MTA домена, а в случае его недоступности - по очереди на следующие за ним по приоритету (резервные) до тех пор, пока сообщение не будет отправлено. Резервные MTA могут передать сообщения на главный после восстановления его работоспособности, а могут выполнить доставку сообщения в почтовый ящик адресата самостоятельно.

Анатомия протокола SMTP


Давайте отправим тестовое письмо, используя протокол SMTP. Он является текстовым протоколом, поэтому для отправки сообщения вместо полнофункционального MUA мы можем использовать telnet (это необходимо для лучшего понимания общих принципов работы протокола SMTP, а также может быть очень полезно при отладке MTA):

# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.domain1.com ESMTP Postfix
EHLO host1.domain1.com
250-mail.domain1.com
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-STARTTLS
250-AUTH PLAIN
250 8BITMIME
MAIL FROM: user1@domain1.com
250 Ok
RCPT TO: user2@domain2.com
250 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
Hello!
.
250 Ok: queued as 24D501771C
QUIT
221 Bye
Connection closed by foreign host.


Немного о том, что происходит в telnet-сессии. Получив приглашение, мы представляемся с помощью команды EHLO, и в ответ получаем список расширений, поддерживаемых тем MTA, к которому мы подключились. Сейчас нас не интересуют расширения, нам просто нужно отправить сообщение. Мы указываем отправителя с помощью команды MAIL FROM: и получателя c помощью команды RCPT TO:. После команды DATA мы вводим содержимое самого письма и завершаем его точкой на новой строке. С помощью команды QUIT мы отключаемся от MTA.


Обратите внимание: содержимое письма, мягко говоря, не соответствует никаким стандартам и совсем не похоже на те примеры «правильных» писем, которые мы приводили. Тем не менее, MTA принял письмо. Если до отправки письма включить прослушивание SMTP-трафика с помощью ethereal, а затем обработать экспортированные текстовые логи средствами grep и sed, мы получим следующие протоколы обмена.

MUA отправителя ↔ MTA отправителя:

Response: 220 mail.domain1.com ESMTP Postfix
Command: EHLO host1.domain1.com
Response: 250-mail.domain1.com
Response: 250-PIPELINING
Response: 250-SIZE 10240000
Response: 250-ETRN
Response: 250-STARTTLS
Response: 250-AUTH PLAIN
Response: 250 8BITMIME
Command: MAIL FROM: user1@domain1.com
Response: 250 Ok
Command: RCPT TO: user2@domain2.com
Response: 250 Ok
Command: DATA
Response: 354 End data with <CR><LF>.<CR><LF>
Message: Hello!
Response: 250 Ok: queued as 24D501771C
Command: QUIT
Response: 221 Bye 

MTA отправителя ↔ MTA получателя:

Response: 220 mail.domain2.com ESMTP Sendmail 8.13.5/8.13.1; Mon, 7 Nov 2005
16:29:00 +0300 (MSK)
Command: EHLO mail.domain1.com
Response: 250-mail.domain2.com Hello mail.domain1.com [xxx.xxx.xxx.xxx],
pleased to meet you
Response: 250-ENHANCEDSTATUSCODES
Response: 250-PIPELINING
Response: 250-8BITMIME
Response: 250-SIZE
Response: 250-DSN
Response: 250-ETRN
Response: 250-AUTH DIGEST-MD5 CRAM-MD5 LOGIN PLAIN
Response: 250-STARTTLS
Response: 250-DELIVERBY
Response: 250 HELP
Command: MAIL FROM:<user1@domain1.com> SIZE=361
Response: 250 2.1.0 <user2@domain2.com>... Sender ok
Message: Received: from host1 (host1.domain1.com [xxx.xxx.xxx.xxx])
Message:     by mail.domain1.com (Postfix) with ESMTP id 24D501771C
Message:     for <user2@domain2.com>; Mon,  7 Nov 2005 16:30:58 +0300 (MSK)
Message: Message-Id: <20051107133058.24D501771C@mail.domain.com>
Message: Date: Mon,  7 Nov 2005 16:30:58 +0300 (MSK)
Message: From: user1@domain1.com
Message: To: undisclosed-recipients:;
Message:
Message: Hello!
Message: .
Message: QUIT
Response: 250 2.0.0 jA7DT0o5090086 Message accepted for delivery
Response: 221 2.0.0 mail.domain2.com closing connection 

Наше однострочное сообщение обзавелось всеми необходимыми заголовками, и теперь вполне соответствует стандартам - MTA также выполнил часть функций MSA. Тем не менее, полагаться на это поведение нельзя - другие MTA или тот же самый, но с более строгими настройками, вправе отказать нам в приеме такого сообщения.

Что еще нужно знать об отправке

Протокол SMTP не позволяет однозначно идентифицировать отправителя сообщения, однако существует возможность потребовать от отправителя авторизоваться - для этого служит расширение AUTH, описанное в RFC 2554 ( SMTP Service Extension for Authentication ). Для реализации этого расширения MTA используют механизм SASL, описанный в RFC 2222 ( Simple Authentication and Security Layer ), который позволяет использовать различные способы передачи и хранения логина и пароля, в том числе и те, которые используют не сам пароль, а его хэш.


Существует также возможность шифровать SMTP-трафик с помощью технологий TLS/SSL (Transport Security Layer / Secure Socket Layer), для чего могут использоваться 2 механизма:

  • Устаревший протокол SMTPS - фактически это тот же самый SMTP, но шифруется весь трафик, начиная от начального приветствия MTA, при этом используется порт 465
  • Расширение STARTTLS, описанное в RFC 2487 ( SMTP Service Extension for Secure SMTP over TLS ) - если клиент MTA (MUA, MSA или другой MTA) поддерживают его, то отправка сообщения может выглядеть, например, так (при этом используется порт 25 - тот же самый, что и для обмена незашифрованными сообщениями):
Response: 220 mail.domain1.com ESMTP Postfix
Command: EHLO host1.domain1.com
Response: 250-mail.domain1.com
Response: 250-PIPELINING
Response: 250-SIZE 10240000
Response: 250-ETRN
Response: 250-STARTTLS
Response: 250-AUTH PLAIN
Response: 250 8BITMIME
Message: STARTTLS
Response: 220 Ready to start TLS
Message: \026\003\001\000S\001\000\000O\003\001\000\033\2144\341\024A\361\
322EP\370yF\257\370x\273?\031<+\326\355\327\337X\347\207\305P\234\000\
000(\0009\0008\0005\0003\0002\000\004\000\005\000/\000\026\000\023\376\377\000
Message: \000\025\000\022\376\376\000\t\000d\000b\000\003\000\006\001\000

Расширение 8BITMIME, описанное в RFC 1652 ( SMTP Service Extension for 8bit-MIME transport ) позволяет использовать тип MIME-кодирования 8bit. Оно не является обязательным, поэтому использовать заголовки, закодированные таким образом, нежелательно.

Мы не будем рассматривать все расширения SMTP, скажем только, что каждому из них посвящен отдельный RFC, а искать их проще по названиям расширений в общем списке RFC.

Кроме использования протокола SMTP существует более простой способ отправить почтовое сообщение - это так называемая локальная отправка, поддерживаемая почти всеми MTA. Общепринятым способом локальной отправки является использование pipe-интерфейса программы sendmail, существуют MUA, которые поддерживают этот способ отправки (KMail, mutt, pine), а mailx вообще никаких других способов, кроме этого, не поддерживает. Простейший shell-скрипт, выполняющий локальную отправку, выглядит так:

#!/bin/sh

/usr/sbin/sendmail -t << EOF
From: user1@domain1.com
To: user2@domain2.com
Subject: Test Message
Hello!
EOF 

Кто занимается транспортировкой сообщений

До сих пор мы говорили только об интерфейсах, предоставляемых MTA, но даже не произносили их названий. Только в протоколах ethereal видно, что на узле mail.domain1.com в качестве MTA используется Postfix, а на узле mail.domain2.com - Sendmail. Это именно та модульность, о которой говорилось выше: существует множество различных MTA, все они реализуют приблизительно одну и ту же функциональность, используют одни и те же протоколы, а как уж они устроены внутри - это их личное дело. Соответственно, дело администратора - выбрать тот MTA, который проще и гибче настраивается, надежнее и быстрее работает, да и вообще, более симпатичен.

Кратко перечислим несколько наиболее распространенных MTA:

  • Sendmail - старожил, самый первый MTA, до сих пор сохраняющий свои позиции, отчасти по инерции (в BSD-системах и во многих дистрибутивах Linux именно он устанавливается по умолчанию), отчасти благодаря возможности очень гибкой настройки. Однако процедура конфигурирования, монолитная архитектура, работа с полномочиями суперпользователя и регулярно обнаруживаемые уязвимости вызывают множество нареканий, поэтому его использование уже становится дурным тоном.
  • Qmail - первая более защищенная и модульная альтернатива Sendmail, за взлом которой учреждена до сих пор никем не полученная премия. Однако этот MTA так и не получил широкого распространения из-за лицензионных ограничений, благодаря которым многие дистрибутивы Linux не включают его в свой состав. Фактически, уже несколько лет Qmail не развивается автором, и чтобы получить нормально работающую систему на его основе, придется собирать его с множеством патчей.
  • Postfix - еще одна альтернатива Sendmail, получившая значительно большее распространение благодаря вменяемой лицензионной политике, модульной архитектуре, высокой производительности, простой процедуре конфигурирования и использованию в некоторых дистрибутивах Linux и в Mac OS X по умолчанию. В журнале уже публиковался цикл статей Андрея Бешкова, посвященных Postfix, поэтому детально рассматривать этот MTA мы не станем.
  • Exim - монолитный MTA подобно Sendmail, однако с безопасностью у него дело обстоит гораздо лучше. Кроме того, Exim претендует на звание MTA с максимальной функциональностью и самой логичной системой конфигурирования, которое, впрочем, требует больших усилий по сравнению с аналогичной процедурой для Postfix. Exim используется по умолчанию в Debian Linux. В журнале уже публиковались статьи, посвященные этому MTA, поэтому останавливаться на нем мы не будем, а пойдем дальше.

Доставка почтовых сообщений

Количество MTA, через которые пройдет письмо, пока не найдет своего адресата, в принципе не ограничено. На практике в большинстве случаев достаточно двух MTA, если домены отправителя и получателя обслуживаются разными MTA (и между ними есть прямой TCP/IP маршрут), или одного в противном случае. Задачей MTA после получения письма для своего домена является сохранение письма в постоянное хранилище, откуда его сможет прочесть адресат с помощью своего MUA. Доставкой письма в это хранилище занимается очень широкий класс ПО, который носит общее название MDA (Mail Delivery Agent).

Когда-то в процедуре доставки ничего сложного не было. Использовалась исключительно push-технология: MTA посредством собственного локального MDA доставлял почтовые сообщения куда-нибудь в /var/mail или /var/spool/mail, а MUA, появившиеся в те времена (mailx, mutt, pine), читали сообщения непосредственно оттуда - при этом они обязаны были находиться на одной машине с MTA или монтировать свои почтовые ящики, например, по NFS. Затем более популярными стали pop-технологии: /var/mail и /var/spool/mail выродились в специализированные серверные хранилища почты с собственными специализированными средствами доставки почты, появились сервисы, предоставляющие доступ к этим хранилищам по протоколам POP3 и IMAP по запросу самого MUA - причем новые MUA (Mozilla, Outlook, The Bat!) по другому себе жизнь уже не мыслят и о /var/mail и /var/spool/mail ничего не знают.

Форматы серверных почтовых хранилищ

На сегодняшний день существует два стандартных формата серверных хранилищ почты ( mbox и Maildir - их стандартность проявляется в том, что доставлять в них почту и извлекать ее оттуда могут различные MDA) и несколько нестандартных (например, файловое хранилище Cyrus, похожее по идеологии на Maildir, но несовместимое с ним, и хранилище DBMail, использующее БД MySQL или PosgreSQL - если использовать эти хранилища, то вместе с их преимуществами мы одновременно резко ограничим себя в выборе MDA для доставки и извлечения почты). Впрочем, в любом случае мы говорим об открытых хранилищах, формат которых документирован (в худшем случае в исходных кодах MDA), поэтому нет никаких препятствий к тому, чтобы написать конвертор из одного хранилища в другое (и такие конверторы есть).

Нестандартные хранилища (Cyrus и DBMail) и MDA, работающие с этими хранилищами, лучше будет рассмотреть в отдельных статьях (статью о DBMail планируется опубликовать в следующем номере журнала, статья о Cyrus IMAP уже публиковалась), а сейчас мы сосредоточим свое внимание на стандартных хранилищах: mbox и Maildir.

Mbox - это целое семейство не совсем совместимых друг с другом форматов, различные модификации которых используются как в хранилищах почты на серверах, так и локально в MUA. Все эти форматы объединяет то, что все сообщения хранятся в одном файле, начинаются с поля From и отделены друг от друга пустой строкой. В процессе доставки новые сообщения дописываются в конец mbox-файла. Если вернуться к нашему примеру письма от user1@domain1.com к user2@domain2.com, то после его сохранения в конце mbox-файла (скорее всего это файл будет называться /var/mail/user2 или /var/spool/mail/user2) добавится следующее:

From user1@domain1.com Sun Oct 23 16:26:52 2005
Return-Path: <user1@domain1.com>
Received: from mail.domain1.com (mail.domain1.com [xxx.xxx.xxx.xxx])
        by mail.domain2.com (8.13.5/8.13.1) with ESMTP id j9NCQqTZ012628
        for <user2@domain2.com>; Sun, 23 Oct 2005 16:26:52 +0400 (MSD)
        (envelope-from user1@domain1.com)
Received: from host1.domain1.com (host1.domain.com [xxx.xxx.xxx.xxx])
        by mail.domain1.com (Postfix) with ESMTP id CEA8840F0
        for <user2@domain2.com>; Sun, 23 Oct 2005 16:33:25 +0400 (MSD)
From: user1@domain1.com
To: user2@domain2.com
Subject: Test Message
Message-Id: <20051023123325.CEA8840F0@mail.domain1.com>
Date: Sun, 23 Oct 2005 16:33:25 +0400 (MSD)

Hello! 

Хранение всех сообщений в одном файле приводит к тому, что писать приложения, осуществляющие одновременное добавление новых сообщений и редактирование уже существующих, не так просто, как хотелось бы, не слишком надежно (возможностей повредить mbox предостаточно), а иногда и просто невозможно (блокировка mbox на запись при доставке сообщений делает невозможной параллельную доставку). Именно это и было причиной появления другого формата - Maildir.

Maildir - это каталог с тремя подкаталогами внутри: tmp, new, cur. При доставке сообщения оно помещается в файл в подкаталоге tmp, имя файла формируется из текущего времени, имени хоста, идентификатора процесса, создавшего этот файл, и некоторого случайного числа - таким образом, гарантируется уникальность имен файлов. После записи в файл всего сообщения создается жестка

Фото автора
Артем Ведун
ИТ-специалист, исследователь цифровой гармонии

Более 15 лет работаю в сфере информационных технологий — от системного администрирования и DevOps до анализа сетевой безопасности. В какой-то момент понял, что цифровые процессы и числа — не только про технологии, но и про закономерности, которые управляют жизнью.

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

В статьях совмещаю строгую логику и символику чисел: от практических гайдов по Linux до разбора цифровых архетипов в бизнесе и киберпространстве.

Верю, что в мире нет случайных чисел — даже в логах сервера.

Последние Статьи

Как выбрать частного SEO‑специалиста в Киеве: практическое руководство

Как выбрать частного SEO‑специалиста в Киеве: практическое руководство

В Киеве существует множество SEO‑услуг: крупные агентства, маленькие студии и частники, с разными подходами и ценами. Для бизнеса важно найти того специалиста, который пониманием задач, прозрачностью ..

Что предлагает KupiFanove.bg? для соц.сетей (smm)

Что предлагает KupiFanove.bg? для соц.сетей (smm)

KupiFanove.bg специализируется на предоставлении услуг по увеличению числа подписчиков и лайков в следующих социальных сетях: Instagram: Покупка подписчиков для повышения авторитета и доверия к ваш..

Почему вам нужен список SEO компаний в Варне?

Почему вам нужен список SEO компаний в Варне?

Сегодня Google обрабатывает более 40 000 поисковых запросов каждую секунду! С такими ошеломляющими цифрами выделиться среди жесткой конкуренции требует профессионального опыта от опытной SEO-команды. ..

Время 02:02 на часах: ангельская нумерология

Время 02:02 на часах: ангельская нумерология

Когда вы в очередной раз случайно бросаете взгляд на часы, и там застыли 02:02, это может быть не просто цифра — это тонкий знак от невидимого мира. Такие зеркальные времена не приходят в жизнь без пр..

Подписаться на рассылку