АйТи Фреш
Главная / Статьи / Серверы и хостинг
Серверы и хостинг

Два сайта — два SMTP-аккаунта у одного провайдера: как научить Postfix не путать логины

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~23 мин чтения
Два сайта — два SMTP-аккаунта у одного провайдера: как научить Postfix не путать логины
Иллюстрация к статье «Два сайта — два SMTP-аккаунта у одного провайдера: как научить Postfix не путать логины».

Ситуация, которую я разбираю у клиентов регулярно: на одном сервере живут два сайта, у каждого свой домен и свой почтовый ящик у одного и того же провайдера, а Postfix упрямо авторизуется под одним логином. Половина писем улетает не от того отправителя, вторая половина отбивается с «Sender address rejected». Ниже — как это устроено внутри, рабочая конфигурация, разбор конкретного случая с цифрами и список мест, где всё ломается из раза в раз.

Почему одного relayhost и одного пароля не хватает

Типовая отправляющая конфигурация выглядит так: relayhost = [smtp.provider.ru]:587, в /etc/postfix/sasl_passwd одна-единственная строка с логином и паролем, smtp_sasl_auth_enable = yes. Это работает ровно до момента, пока с сервера пишет один домен. Как только на той же машине появляется второй сайт со своим ящиком у того же провайдера, конструкция ломается тихо и некрасиво.

Механика простая, если прочитать документацию буквально. Параметр smtp_sasl_password_maps описан как «lookup tables with one username:password entry per sender, remote hostname or next-hop domain» — то есть ключом поиска может быть отправитель, имя хоста или домен следующего перехода. Но дальше идёт ключевая оговорка: «Per-sender lookup is done only when sender-dependent authentication is enabled». По умолчанию smtp_sender_dependent_authentication = no, и поиск по отправителю не выполняется вообще. Ключ — только назначение. А назначение у обоих сайтов одно и то же: [smtp.provider.ru]:587. Одна запись в таблице, один логин, и Postfix даже не подозревает, что вы хотели чего-то другого.

Стоит отдельно проговорить, чего в этой схеме нет. Postfix не смотрит на то, какой сайт сгенерировал письмо, не различает пользователей php-fpm и не заглядывает в заголовки. Для маршрутизатора существует ровно одна характеристика письма, по которой можно принять решение об учётке, — адрес отправителя конверта. Всё остальное надо к этому адресу привести, и обычно именно на этом шаге и застревают: конфиг Postfix правильный, а приложение отдаёт не тот конверт.

Наружу это выходит двумя способами. Строгий провайдер отбивает письмо на этапе MAIL FROM с ответом вида 553 5.7.1 Sender address rejected: not owned by user — и вы хотя бы видите проблему в логе. Провайдер помягче молча переписывает конверт в адрес аутентифицированного аккаунта: письма магазина уходят от имени корпоративного ящика, ответы клиентов падают не туда, суточный лимит одного ящика съедается за двоих, а статистику доставки по сайтам собрать невозможно в принципе. Второй вариант хуже — он не болит, пока кто-нибудь не спросит, почему клиенту ответили с чужого адреса.

Если записи в `smtp_sasl_password_maps` не нашлось совсем, Postfix не пытается аутентифицироваться вовсе — и вы получите `530 5.7.0 Authentication required`. Это не «пароль неверный», это «пароль не нашли». Ошибки принципиально разные, а лечат их одинаково — тычут в пароль.
Памятка: Почему одного relayhost и одного пароля не хватает — схема
Памятка: Почему одного relayhost и одного пароля не хватает. Открыть схему в полном размере

Три параметра и две таблицы: рабочий конфиг

Postfix умеет отдельные аккаунты для отдельных отправителей начиная с версии 2.3 — то есть с 2006 года. Никакой экзотики, никаких патчей, всё в штатном SASL_README. Нужны три параметра в main.cf и две таблицы. Вот база, от которой я всегда стартую:

# /etc/postfix/main.cf
smtp_sasl_auth_enable = yes
smtp_sender_dependent_authentication = yes
sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
smtp_sasl_tls_security_options = noanonymous
relayhost = [smtp.provider.ru]:587

Дальше — таблицы. В sender_relay мы говорим, куда сдавать письмо для конкретного отправителя, в sasl_passwd — под каким логином. Обратите внимание на последнюю строку sasl_passwd: это учётка для общего relayhost, она нужна для всего, что не попало ни в одно правило по отправителю.

# /etc/postfix/sender_relay
shop@shop.example.ru      [smtp.provider.ru]:587
@shop.example.ru          [smtp.provider.ru]:587
@corp.example.ru          [smtp.provider.ru]:587

# /etc/postfix/sasl_passwd
shop@shop.example.ru      shop@shop.example.ru:PasswordOne
@shop.example.ru          shop@shop.example.ru:PasswordOne
@corp.example.ru          info@corp.example.ru:PasswordTwo
# логин для общего relayhost
[smtp.provider.ru]:587    info@corp.example.ru:PasswordTwo

Порядок поиска описан в мануале однозначно и его стоит держать в голове: «the Postfix SMTP client will search the SASL password file by sender address before it searches that same file by destination», а демон trivial-rewrite ищет relayhost по отправителю и использует глобальный relayhost «only as a final resort». Обе таблицы просматриваются по полному адресу конверта и по @domain — поэтому строка вида @shop.example.ru закрывает все ящики домена одним правилом, и это тот случай, когда я предпочитаю доменную запись поимённой. Отдельная тонкость: результат DUNNO в sender_dependent_relayhost_maps (Postfix 2.6 и новее) прекращает поиск, не переопределяя глобальный relayhost — удобно, когда для одного адреса надо явно вернуться к дефолту.

С конкретными провайдерами есть нюанс с портами, и его лучше решить до правки таблиц. У Яндекс Почты официальные параметры отправки — smtp.yandex.ru, порт 465 с SSL, либо 587, если клиент начинает соединение без шифрования и поднимает его через STARTTLS; логин — полный адрес ящика, пароль — не от аккаунта, а созданный пароль приложения. У Почты Mail.ru в справке для почтовых программ указан smtp.mail.ru, порт 465 с SSL/TLS, и тоже пароль для внешнего приложения вместо основного. Порт 587 работает с обычной схемой из примера выше (smtp_tls_security_level = encrypt, STARTTLS). Порт 465 — это не STARTTLS, а TLS с первого байта, и Postfix подключается к нему только с smtp_tls_wrappermode = yes (Postfix 3.0 и новее), который по документации требует smtp_tls_security_level = encrypt или строже. Без wrappermode соединение с 465 просто висит до таймаута и падает в deferred с невнятным lost connection.

# Вариант 1: всё через Яндекс на 587 (STARTTLS) — схема из примера выше
relayhost = [smtp.yandex.ru]:587
smtp_tls_security_level = encrypt

# Вариант 2: провайдер только на 465 (Mail.ru) — SUBMISSIONS/wrappermode
relayhost = [smtp.mail.ru]:465
smtp_tls_security_level = encrypt
smtp_tls_wrappermode = yes

# /etc/postfix/sasl_passwd — ключ повторяет форму relayhost буква в букву
[smtp.yandex.ru]:587      info@corp.example.ru:ПарольПриложения
@shop.example.ru          shop@shop.example.ru:ПарольПриложения2

Если в одном сервере смешиваются отправители на 587 и на 465, глобальный smtp_tls_wrappermode = yes ломает первых. Тогда я завожу в master.cf отдельный транспорт, например smtps-out unix - - n - - smtp -o smtp_tls_wrappermode=yes -o smtp_tls_security_level=encrypt, и направляю в него нужных отправителей через sender_dependent_default_transport_maps со значением вида smtps-out:[smtp.mail.ru]:465. Ключ в sasl_passwd при этом остаётся по адресу отправителя, а для назначения — строго [smtp.mail.ru]:465.

Актуальная стабильная ветка на сентябрь 2026 — Postfix 3.11 (последний релиз 3.11.7 от 7 сентября 2026, параллельно обновлены legacy-ветки 3.10.14, 3.9.15, 3.8.21, 3.7.23). В ней, кстати, поменялся дефолт `smtp_tls_security_level`: при `compatibility_level ≥ 3.11` это `may`, в более старых версиях и при меньшем `compatibility_level` — пусто, то есть фактически `none`. Для отправки через провайдерский релей всё равно ставьте `encrypt` явно — плейнтекстовый логин в открытом канале не нужен никому.
Два сайта — два SMTP-аккаунта у одного провайдера: как научить Postfix не путать логины — схема
Схема к статье. Открыть схему в полном размере

Главная ловушка: envelope sender — это не то, что в заголовке From

Девять из десяти обращений «я всё настроил по инструкции, а логин по-прежнему один» упираются в это. Обе таблицы ищутся по адресу отправителя конверта (envelope sender, он же MAIL FROM), а не по заголовку From:, который видит человек в почтовом клиенте. Сайт может рисовать в письме сколь угодно красивый From: Магазин <shop@shop.example.ru> — если в конверте стоит www-data@srv01.localdomain, Postfix честно не найдёт совпадения ни в sender_relay, ни в sasl_passwd и уедет на общий relayhost с общим логином.

Кто портит конверт чаще всего: PHP-функция mail() без пятого аргумента (-f), скрипты из cron, у которых отправитель собирается из имени юзера и hostname, самописные рассыльщики через sendmail -t, и любой софт, где в настройках есть только поле «От кого» без отдельного «Return-Path». В WordPress та же история: wp_mail() вызывает PHPMailer::setFrom() с третьим аргументом false, то есть меняет только заголовок, а конверт остаётся за sendmail_path и настройками PHP; в Bitrix отправка тоже идёт через mail() или собственный SMTP-модуль, и конверт надо проверять отдельно. Проверяется одной строкой в логе — смотрите поле from= у записи cleanup/qmgr, там именно конверт:

# что реально стоит в конверте
grep -E 'from=<' /var/log/mail.log | tail -20
# отправитель писем, застрявших в очереди
mailq | head
postcat -q <QUEUEID> | head -40

Лечится в порядке предпочтения. Первое и правильное — заставить приложение подставлять нужный конверт: в PHP это mail.force_extra_parameters = -f shop@shop.example.ru в отдельном пуле php-fpm, или sendmail_path = /usr/sbin/sendmail -t -i -f shop@shop.example.ru. Второе, если до приложения не дотянуться, — sender_canonical_maps, но с открытыми глазами: он переписывает и конверт, и заголовки отправителя, то есть меняет видимого автора письма. Третье, самое грязное, но иногда единственное, — разнести сайты по разным системным пользователям и переписать отправителя по локальной части через регулярку. Я хожу этим путём только когда первые два закрыты.

Не начинайте отладку с паролей. Сначала докажите, какой адрес стоит в конверте, — в половине случаев на этом расследование и заканчивается.

Разбор из практики: магазин пряжи «Шерсть и нить», два сайта, один провайдер

Клиент — магазин пряжи «Шерсть и нить» на 48 рабочих мест: розничные точки, склад, интернет-магазин и офис; обслуживаем инфраструктуру целиком. На отдельном VPS (Debian 12, Postfix 3.7.11 из репозитория, nginx + php-fpm 8.2) живут два сайта: корпоративный сайт с оптовым прайсом и мастер-классами на corp.example.ru и интернет-магазин пряжи на shop.example.ru. Почта у обоих у одного провайдера, ящики разные, лимит — 500 писем в сутки на ящик. Обращение было сформулировано так: «покупатели не получают подтверждения заказов, а в почту бухгалтерии сыплются ответы про мотки и доставку».

Картина за трое суток по логам: 1 240 отказов 553 5.7.1 Sender address rejected от релея провайдера, очередь deferred разбухла до 900+ писем, суточный лимит корпоративного ящика выбирался к 15:00, после чего сыпалось 450 4.7.1 Too many messages. В main.cf был единственный relayhost = [smtp.provider.ru]:587 и одна строка в sasl_passwd — с логином бухгалтерии, потому что исторически сначала настроили корпоративный сайт. Магазин, добавленный годом позже, всё это время отправлял под чужой учёткой; провайдер до какого-то момента переписывал конверт молча, а после ужесточения политики начал отбивать.

Развернул схему из раздела выше: два правила по @domain в обеих таблицах плюс запись для общего relayhost. И тут же наступил на две классические грабли. Первая: в relayhost был порт :587, а в sasl_passwd я по инерции написал [smtp.provider.ru] без порта — мануал на этот счёт предельно ясен, «если вы указали [ и ] или нестандартный порт в relayhost, то же самое должно быть в smtp_sasl_password_maps», и без совпадения записи просто не находятся. Вторая: правки внёс, postmap не сделал — Postfix продолжал читать старый .db, и десять минут я смотрел в неизменившийся лог. Обе ошибки диагностировались одной командой postmap -q.

Отдельно вылез конверт. Магазин слал письма через mail() без -f, поэтому в конверте стоял www-data@yarn-web — ни одно правило по отправителю не срабатывало даже после исправления скобок. Добавил в пул php-fpm магазина php_admin_value[mail.force_extra_parameters] = -f shop@shop.example.ru, перезапустил пул. Итог через неделю наблюдения: отказов 553 — ноль, письма обоих доменов уходят под своими логинами, в логе у каждой доставки видно нужный sasl_username, лимиты разъехались (магазин 380–410 писем/сутки, корпоративный сайт 35–45), очередь пустая. Суммарно работа заняла около двух часов, из которых полтора — поиск того самого www-data.

Если провайдер молча переписывает конверт вместо отказа — проблема не исчезла, она просто не болит. Проверьте `Return-Path` во входящем письме от своего же сайта: там будет чужой адрес.
Цифры и версии: Разбор из практики: магазин пряжи «Шерсть и нить», два сайта, один провайдер — схема
Цифры и версии: Разбор из практики: магазин пряжи «Шерсть и нить», два сайта, один провайдер. Открыть схему в полном размере

Отладка: пять команд, которыми я закрываю вопрос

Отладка тут скучная и полностью детерминированная — никакой магии, просто последовательность проверок. Сначала смотрю, что вообще включено, потом — находятся ли ключи, потом — что уходит в сеть.

# 1. что включено на самом деле (не то, что в файле, а то, что применилось)
postconf -n | grep -E 'sender_dependent|sasl|relayhost'

# 2. находится ли ключ ровно так, как его ищет Postfix
postmap -q "shop@shop.example.ru" hash:/etc/postfix/sender_relay
postmap -q "@shop.example.ru"     hash:/etc/postfix/sasl_passwd
postmap -q "[smtp.provider.ru]:587" hash:/etc/postfix/sasl_passwd

# 3. тестовое письмо с явным конвертом
sendmail -f shop@shop.example.ru -t <<'EOF'
From: Shop <shop@shop.example.ru>
To: proverka@example.com
Subject: sender-dependent test

test
EOF

# 4. смотрим, куда и с каким результатом ушло
tail -f /var/log/mail.log | grep -E 'from=<|relay=|status=|SASL'
# при необходимости — временно видеть AUTH-диалог с релеем
postconf -e 'debug_peer_list = smtp.provider.ru' && postfix reload

# 5. пересборка таблиц и применение
postmap /etc/postfix/sender_relay /etc/postfix/sasl_passwd && postfix reload

Пункт 2 — самый недооценённый. postmap -q спрашивает таблицу тем же способом, что и сам Postfix: если команда молчит, значит записи нет, и никакие рассуждения «но она же там написана» не помогают. Чаще всего молчание означает лишний пробел вместо табуляции в неожиданном месте, несовпадающие скобки, отсутствующий порт или то, что вы забыли postmap и спрашиваете свежий текстовый файл при старом индексе.

Пункт 4 даёт финальное доказательство. Пункт 4 даёт финальное доказательство, но с оговоркой: SMTP-клиент Postfix не пишет в строку доставки имя учётки — поле sasl_username= в логе ставит только smtpd для входящих подключений. Поэтому для исходящей почты я смотрю связку from=<…> у qmgr и relay=/status= у smtp той же очереди, а логин подтверждаю двумя способами: Return-Path и заголовки провайдера в тестовом письме, пришедшем на внешний ящик, либо временный debug_peer_list с именем релея — тогда в логе виден весь AUTH-диалог. Если вместо status=sent стоит 530 5.7.0 Authentication required — Postfix не нашёл пароль и пошёл без аутентификации; если SASL authentication failed; server … said: 535 — пароль нашёлся, но не подошёл. После отладки debug_peer_list обязательно очистить.

Есть ещё один приём, который экономит время на боевом сервере: не гонять тестовые письма наружу, а посмотреть решение маршрутизатора напрямую. Решение о relayhost принимает демон trivial-rewrite, и напрямую его не спросить, но ключи его таблиц проверяются тем же postmap -q, а для рискованных правок надёжнее поднять отдельный тестовый инстанс через postmulti -e create с копией конфигурации и гонять проверки там. Особенно это выручает, когда сервер обслуживает боевую почту компании и «поэкспериментировать полчасика» на нём нельзя: любая ошибка в sender_relay немедленно кладёт весь исходящий поток в очередь.

И маленькая привычка, которая окупается: после каждой правки сохраняйте вывод postconf -n в файл рядом с конфигом и коммитьте вместе с main.cf. Через полгода, когда письма внезапно поедут не туда, вы за минуту увидите разницу между «как было» и «как стало» — вместо того чтобы восстанавливать историю по памяти и датам изменения файлов.

Логи с SASL-переговорами не выкладывайте на форумы и в чаты как есть: логин и пароль из base64 разворачиваются одной командой. В SASL_README прямо сказано, что пароль из base64-формы восстанавливается тривиально, и это не паранойя. То же касается вывода `debug_peer_list`.

Где ломается из раза в раз

Список ниже — концентрат того, что я вижу на чужих серверах. Первые четыре пункта закрывают, по ощущениям, девять случаев из десяти; остальные — редкие, но злые.

Отдельно про производительность. Включение smtp_sender_dependent_authentication = yes документировано как отключающее кэширование SMTP-соединений — «disables SMTP connection caching to ensure that mail from different senders will use the appropriate credentials». Логика понятна: переиспользовать сессию, открытую под другим логином, нельзя. На обычном корпоративном потоке — десятки, сотни писем в сутки — вы этого не заметите. А вот если сервер гонит массовую рассылку в несколько тысяч писем, каждое письмо получит собственный TCP+TLS+AUTH хендшейк, и время выгребания очереди вырастет заметно. Это ровно тот случай, когда стоит вынести рассылку в отдельный инстанс Postfix или в API провайдера, а sender-dependent оставить транзакционным письмам.

И про пароли. До Postfix 3.9 разделителем логина и пароля жёстко служит двоеточие, поэтому пароль с двоеточием внутри в sasl_passwd не записать никак — только менять пароль. В 3.9 и новее появился smtp_sasl_password_result_delimiter, которым разделитель можно переназначить на любой символ, не встречающийся в имени пользователя. На Debian 12 с Postfix 3.7 этого параметра ещё нет — проверяйте postconf -d | grep result_delimiter, прежде чем закладываться.

Проверьте DMARC-отчёты через неделю после внедрения. Разделили логины — теперь у вас два потока с разными SPF и DKIM, и если домен второго сайта у провайдера не подтверждён, вы поменяли «письма от чужого имени» на «письма в спаме».
Памятка: Где ломается из раза в раз — схема
Памятка: Где ломается из раза в раз. Открыть схему в полном размере

Когда я это не делаю и что беру вместо

Sender-dependent схема хороша, когда назначение у отправителей одно или похожее, а различаются только учётки. Если же сайтам нужны разные транспорты, разные исходящие IP или разные политики TLS, я разворачиваю несколько инстансов Postfix через postmulti и развожу трафик транспортами. Это дороже в обслуживании, зато каждая рассылка изолирована полностью, включая очередь, лимиты и логи — при разборе инцидента экономит часы.

Второй вариант, который часто оказывается лучше всего перечисленного: не тащить письма сайта через SMTP-релей вообще. Транзакционные письма магазина отдать в API почтового сервиса прямо из приложения, а Postfix оставить системной почте и уведомлениям от cron. Тогда вопрос «каким логином» исчезает вместе с проблемой, а доставляемость и аналитика получаются лучше любого самосбора. Спорный момент, признаю: это перекладывание задачи с админа на разработчика, и не в каждом проекте на это готовы. Но если разработчик под рукой — предлагайте.

И честно про риски: сама по себе настройка обратима и безопасна. Худшее, что случается при ошибке, — письма остаются в очереди (smtp_sasl_auth_soft_bounce = yes по умолчанию их не отбивает) и уходят после исправления. Поэтому не бойтесь трогать; бойтесь трогать без postconf -n до и после и без тестового письма с явным -f. И держите main.cf под контролем версий — за пять лет через сервер проходит десяток правок, и без истории вы не вспомните, зачем там появилась третья строка в sender_relay.

Практический приоритет: сначала конверт, потом таблицы, потом пароли. В обратном порядке вы потратите день.

Частые вопросы

Почему Postfix игнорирует мою запись в sender_relay, хотя адрес написан правильно?

Три причины по частоте. Первая: в конверте письма стоит не тот адрес, который вы видите в поле From — проверьте поле `from=<>` в mail.log. Вторая: забыт `postmap`, и читается старый индексный файл. Третья: несовпадение формы записи — если в relayhost указаны квадратные скобки или нестандартный порт, ровно та же форма должна быть в таблицах. Проверяется командой `postmap -q «адрес» hash:/etc/postfix/sender_relay`: если она молчит, записи для Postfix не существует.

Нужно ли прописывать каждый ящик отдельно или хватит записи по домену?

Таблицы просматриваются и по полному адресу конверта, и по `@domain`. Я почти всегда обхожусь доменными записями вида `@shop.example.ru` — это одна строка вместо десяти и никаких сюрпризов при появлении нового ящика. Поимённые записи имеют смысл, только когда внутри одного домена разным адресам действительно нужны разные учётки провайдера.

Что будет с письмами, для которых подходящей записи нет?

Они уйдут через глобальный `relayhost` с той учёткой, которая записана в sasl_passwd по ключу назначения. Поэтому строку для общего relayhost надо держать всегда: без неё Postfix не найдёт пароль вообще и попытается отправить без аутентификации, получив `530 5.7.0 Authentication required`.

Не просядет ли производительность отправки?

Включение `smtp_sender_dependent_authentication = yes` отключает кэширование SMTP-соединений — иначе сессию, открытую под одним логином, могли бы переиспользовать письма другого отправителя. На потоке в сотни писем в сутки это незаметно. На массовых рассылках в тысячи писем каждое отправление получает свой TLS-хендшейк и AUTH, и очередь выгребается заметно медленнее — такой трафик лучше вынести в отдельный инстанс Postfix или в API почтового сервиса.

Пароль от ящика содержит двоеточие — как записать его в sasl_passwd?

До Postfix 3.9 — никак, разделитель логина и пароля жёстко зашит как двоеточие, придётся менять пароль. Начиная с 3.9 появился параметр `smtp_sasl_password_result_delimiter`, которым разделитель переназначается на любой символ без пробелов, не встречающийся в имени пользователя. Проверьте наличие параметра командой `postconf -d | grep result_delimiter` — например, в Postfix 3.7 из Debian 12 его ещё нет.

Нужно ли что-то менять в SPF и DKIM после разделения аккаунтов?

Да, и это половина задачи. Каждый домен нужно отдельно подтвердить и подписать у провайдера: раньше оба сайта уходили под одним аккаунтом с его SPF и DKIM, теперь потоков два. Если домен второго сайта у провайдера не настроен, вы поменяете проблему «письма от чужого имени» на проблему «письма в спаме». Через неделю после внедрения обязательно посмотрите DMARC-отчёты по обоим доменам.

Яндекс или Mail.ru на 465 — почему письма висят в очереди с lost connection?

Потому что 465 — это TLS с самого начала соединения (SUBMISSIONS), а по умолчанию SMTP-клиент Postfix ждёт открытый SMTP и STARTTLS. Для 465 нужны `smtp_tls_wrappermode = yes` и `smtp_tls_security_level = encrypt` (Postfix 3.0+). У Яндекса можно вместо этого перейти на официальный порт 587 со STARTTLS; у Mail.ru в справке указан только 465. И не забудьте, что обоим провайдерам нужен пароль приложения, а ключ в `sasl_passwd` должен совпадать с relayhost вместе с портом.

Столкнулись с похожей задачей? Обращайтесь — решим

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

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи