Где 1С хранит адрес почты пользователя и как его прочитать
Содержание
Email пользователя в типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) лежит не в пользователе информационной базы, а в табличной части КонтактнаяИнформация справочника Пользователи. Получить его проще всего запросом к этой табличной части с отбором по типу АдресЭлектроннойПочты, а текущего пользователя взять функцией Пользователи.ТекущийПользователь().
Если в карточке адрес не заполнен, есть три запасных источника. Учётная запись электронной почты из справочника УчетныеЗаписиЭлектроннойПочты подходит, когда нужен адрес отправителя. Active Directory через LDAP выбирают в доменной сети, где почта ведётся централизованно. HTTP-запрос к внешнему API нужен, если справочник сотрудников живёт в другой системе: кадровом портале или Microsoft 365.
Откуда 1С берёт адрес почты: метаданные и справочники
В платформе 1С:Предприятие 8.3 есть два разных «пользователя», и их часто путают.
- 👤 Пользователь информационной базы — объект
ПользовательИнформационнойБазы. Это логин, пароль, роли, привязка к учётной записи Windows. Его получают черезПользователиИнформационнойБазы.ТекущийПользователь(). Адрес почты типовые конфигурации здесь не ведут. - 📇 Элемент справочника
Пользователи— прикладная карточка из Библиотеки стандартных подсистем (БСП). В ней ФИО, подразделение, физическое лицо и контактная информация. Email хранится здесь.
Связь между ними — реквизит ИдентификаторПользователяИБ в справочнике. Поэтому код, который ищет почту, всегда работает со ссылкой на СправочникСсылка.Пользователи.
Где адрес заполняют руками: Администрирование → Настройки пользователей и прав → Пользователи, открыть карточку, поле электронной почты в блоке контактной информации.
Как устроено хранение внутри:
| Что | Где в метаданных | Комментарий |
|---|---|---|
| Строки контактной информации | Справочник.Пользователи.КонтактнаяИнформация | Табличная часть, по строке на каждый вид КИ |
| Тип строки | Поле Тип, перечисление ТипыКонтактнойИнформации | Для почты — АдресЭлектроннойПочты |
| Вид строки | Поле Вид, справочник ВидыКонтактнойИнформации | Предопределённый вид EmailПользователя |
| Сам адрес | Поле Представление | Строка вида ivanov@firma.ru |
Отбирайте по полю Тип, а не только по Вид. Если администратор добавил свой вид почты, например «Рабочий email», отбор по EmailПользователя его пропустит.
У сотрудников есть ещё одна точка: реквизит ФизическоеЛицо в карточке пользователя. Контактная информация физического лица ведётся отдельно, в табличной части справочника ФизическиеЛица. В ЗУП там часто лежит личная почта для расчётных листков, и она может не совпадать с рабочей.
Получение email пользователя кодом через запрос
Запросы и обращения к справочникам выполняются на сервере. С клиента вызываем серверную функцию, она возвращает строку.
Адрес текущего пользователя
&НаСервереБезКонтекста
Функция EmailТекущегоПользователя()
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| КИ.Представление КАК Адрес
|ИЗ
| Справочник.Пользователи.КонтактнаяИнформация КАК КИ
|ГДЕ
| КИ.Ссылка = &Пользователь
| И КИ.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.АдресЭлектроннойПочты)
|
|УПОРЯДОЧИТЬ ПО
| ВЫБОР
| КОГДА КИ.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.EmailПользователя)
| ТОГДА 0
| ИНАЧЕ 1
| КОНЕЦ,
| КИ.НомерСтроки";
Запрос.УстановитьПараметр("Пользователь", Пользователи.ТекущийПользователь());
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат СокрЛП(Выборка.Адрес);
КонецЕсли;
Возврат "";
КонецФункции
Что здесь важно:
Пользователи.ТекущийПользователь()— функция общего модуля БСП. Она возвращает ссылку на элемент справочника, а не объект платформы.- Сортировка ставит основной вид
EmailПользователяпервым. Если его нет, берётся первая строка любого почтового вида. УстановитьПривилегированныйРежим(Истина)нужен, если у роли пользователя нет права читать справочник целиком. В типовых конфигурациях такой код лучше вынести в серверный общий модуль, а не держать в модуле формы.
Адреса всех пользователей списком
Для рассылки или выгрузки удобнее один запрос на всех:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Пользователи.Ссылка КАК Пользователь,
| Пользователи.Наименование КАК ФИО,
| ЕСТЬNULL(КИ.Представление, """") КАК Адрес
|ИЗ
| Справочник.Пользователи КАК Пользователи
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Пользователи.КонтактнаяИнформация КАК КИ
| ПО (КИ.Ссылка = Пользователи.Ссылка)
| И (КИ.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.АдресЭлектроннойПочты))
|ГДЕ
| НЕ Пользователи.ПометкаУдаления
| И НЕ Пользователи.Недействителен
| И НЕ Пользователи.Служебный
|
|УПОРЯДОЧИТЬ ПО
| ФИО";
Таблица = Запрос.Выполнить().Выгрузить();
Левое соединение оставляет в выборке пользователей без почты: у них в колонке Адрес будет пустая строка. По ней удобно найти, кому заполнить карточку. Если у человека два почтовых адреса, он попадёт в таблицу двумя строками.
Отбор по Недействителен и Служебный убирает уволенных и технических пользователей вроде обмена данными. Без него рассылка уйдёт и на служебные учётки.
Через программный интерфейс БСП
В модуле УправлениеКонтактнойИнформацией есть функции для чтения КИ объекта. Их состав и параметры менялись между версиями БСП, поэтому перед использованием откройте модуль в конфигураторе и найдите экспортную функцию по слову «КонтактнаяИнформация». Прямой запрос из примера выше работает одинаково во всех актуальных релизах.
Email из учётной записи электронной почты
Бывает, что нужен не адрес из карточки, а адрес, с которого пользователь реально отправляет письма из 1С. Он хранится в справочнике УчетныеЗаписиЭлектроннойПочты, реквизит АдресЭлектроннойПочты.
В современных версиях БСП учётная запись может быть личной: у неё заполнен владелец — пользователь. Тогда адрес отправителя находится запросом с отбором по владельцу. Если владельца нет, учётная запись общая, например buh@firma.ru, и к конкретному человеку её не привязать.
Когда какой источник брать:
| Задача | Источник |
|---|---|
| Уведомить пользователя о событии | Контактная информация справочника Пользователи |
| Подставить «От кого» в письмо | Учётная запись электронной почты |
| Отправить расчётный листок сотруднику | Контактная информация физического лица |
История изменений адреса и регистры сведений
В текущих конфигурациях отдельного регистра под контактную информацию пользователей нет: всё лежит в табличной части справочника. Регистр сведений
КонтактнаяИнформация встречается в старых решениях эпохи 8.2 — УТ 10.3, ЗУП 2.5, Бухгалтерии 2.0. Там адрес читают запросом к регистру с отбором по измерениям Объект и Тип, а значение берут из ресурса Представление.
Историю изменения адреса в типовых конфигурациях на 8.3 можно восстановить двумя способами:
- 🗂 Версионирование объектов. Если в настройках программы включено хранение версий для справочника «Пользователи», каждая запись карточки сохраняется в регистр сведений
ВерсииОбъектов. В карточке пользователя это видно через команду истории изменений, а версии можно сравнить между собой. - 📜 Журнал регистрации. В нём фиксируется факт изменения элемента справочника, кто и когда его записал. Старое значение адреса журнал не хранит, только событие.
Хранение истории с датой действия в табличной части КИ поддерживается для адресов, а не для почты. Если важно знать, какой email был у пользователя на прошлую дату, включайте версионирование.
Получение почты из Active Directory через LDAP
В доменной сети адрес почты часто уже лежит в атрибуте mail учётной записи AD. Встроенного объекта для LDAP в платформе нет, но на Windows-сервере работает COM-провайдер ADsDSOObject.
Сначала узнаём логин пользователя в Windows. Свойство ПользовательОС возвращает строку вида \\CORP\ivanov, из неё нужна последняя часть:
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Части = СтрРазделить(ПользовательИБ.ПользовательОС, "\", Ложь);
Логин = ?(Части.Количество() > 0, Части[Части.Количество() - 1], "");
Затем ищем запись в каталоге:
Функция EmailИзActiveDirectory(Логин) Экспорт
Адрес = "";
Попытка
Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.Provider = "ADsDSOObject";
Соединение.Open("Active Directory Provider");
Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = Соединение;
Команда.CommandText = "<LDAP://DC=corp,DC=local>;"
+ "(&(objectCategory=person)(objectClass=user)(sAMAccountName=" + Логин + "));"
+ "mail;subtree";
Записи = Команда.Execute();
Если Не Записи.EOF Тогда
Значение = Записи.Fields("mail").Value;
Если Значение <> Неопределено И Значение <> NULL Тогда
Адрес = СокрЛП(Строка(Значение));
КонецЕсли;
КонецЕсли;
Записи.Close();
Соединение.Close();
Исключение
ЗаписьЖурналаРегистрации("Интеграция.ActiveDirectory",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Возврат Адрес;
КонецФункции
DC=corp,DC=local замените на свой домен. Что учесть:
- Где выполняется код. В клиент-серверном варианте функция работает на сервере 1С, под учётной записью службы агента. У этой учётки должны быть права на чтение каталога. Локальная системная учётная запись на рядовом сервере в домен часто не ходит.
- Только Windows. COM-объекты на сервере 1С под Linux недоступны. Там используют HTTP-шлюз к каталогу или выгрузку атрибутов по расписанию.
- Экранирование. Логин подставляется в фильтр LDAP. Символы
*,(,)и\в нём нужно экранировать, иначе фильтр вернёт чужие записи. - Пустой
mail. Если почтовый ящик заведён в Exchange, но атрибут не заполнен, смотритеuserPrincipalNameилиproxyAddresses. Основной адрес вproxyAddressesидёт с префиксомSMTP:в верхнем регистре.
Не ходите в AD при каждом открытии формы. Надёжнее раз в сутки регламентным заданием переносить адреса в контактную информацию пользователей и дальше читать их обычным запросом.
Адрес через HTTP-запрос к внешнему API
Если учётные записи ведутся в облаке или кадровом портале, адрес берут по HTTP. Пример для Microsoft Graph: приложению в Entra ID нужно право User.Read.All, токен получаете заранее по схеме client credentials.
Функция EmailИзMicrosoftGraph(ИмяВхода, Токен) Экспорт
Соединение = Новый HTTPСоединение("graph.microsoft.com", 443,,,, 30,
Новый ЗащищенноеСоединениеOpenSSL);
Адрес = "/v1.0/users/"
+ КодироватьСтроку(ИмяВхода, СпособКодированияСтроки.КодировкаURL)
+ "?$select=mail,userPrincipalName";
Запрос = Новый HTTPЗапрос(Адрес);
Запрос.Заголовки.Вставить("Authorization", "Bearer " + Токен);
Запрос.Заголовки.Вставить("Accept", "application/json");
Попытка
Ответ = Соединение.Получить(Запрос);
Исключение
ЗаписьЖурналаРегистрации("Интеграция.Graph", УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат "";
КонецПопытки;
Если Ответ.КодСостояния <> 200 Тогда
ЗаписьЖурналаРегистрации("Интеграция.Graph", УровеньЖурналаРегистрации.Предупреждение, , ,
СтрШаблон("Код ответа %1: %2", Формат(Ответ.КодСостояния, "ЧГ=0"),
Ответ.ПолучитьТелоКакСтроку("UTF-8")));
Возврат "";
КонецЕсли;
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку("UTF-8"));
Данные = ПрочитатьJSON(Чтение, Истина);
Чтение.Закрыть();
Почта = Данные.Получить("mail");
Возврат ?(ЗначениеЗаполнено(Почта), СокрЛП(Почта), "");
КонецФункции
Почему именно так:
- 🔑
ПрочитатьJSON(Чтение, Истина)читает ответ вСоответствие. В структуру прочитать не получится: ключ@odata.contextне является допустимым именем свойства, и платформа выдаст ошибку. - 🧾 Поле
mailв ответе может бытьnull. Он превращается вНеопределено, иЗначениеЗаполненоэто отсекает. - ⏱ Таймаут 30 секунд не даёт форме зависнуть, если внешний сервис не отвечает.
- 🔒 Токен не храните в константе открытым текстом. В БСП для секретов есть безопасное хранилище данных — в нём же типовые конфигурации держат пароли учётных записей почты.
Для своего кадрового портала схема та же: другой хост, другой путь, своя авторизация.
Проверка адреса и обработка ошибок
Полученная строка ещё не гарантирует, что письмо дойдёт. В поле КИ пользователи вписывают что угодно: два адреса через запятую, пробелы, «нет».
Минимальная проверка своими силами:
Функция ПохожеНаEmail(Знач Адрес)
Адрес = СокрЛП(Адрес);
Если СтрНайти(Адрес, " ") > 0 Или СтрЧислоВхождений(Адрес, "@") <> 1 Тогда
Возврат Ложь;
КонецЕсли;
Части = СтрРазделить(Адрес, "@");
Возврат СтрДлина(Части[0]) > 0 И СтрНайти(Части[1], ".") > 1
И Не СтрЗаканчиваетсяНа(Части[1], ".");
КонецФункции
В БСП есть готовая функция ОбщегоНазначенияКлиентСервер.АдресЭлектроннойПочтыСоответствуетТребованиям. Она строже самописной проверки, и в типовой конфигурации лучше вызывать её.
Если в поле может быть несколько адресов, сначала разбейте строку по ; и , через СтрРазделить, затем проверьте каждый адрес отдельно.
Что делать, если адреса нет нигде: не подставляйте «заглушку» и не шлите письмо в пустоту. Верните пустую строку, запишите событие в журнал регистрации с указанием пользователя и покажите администратору список людей без почты. Этот список даёт запрос из второго раздела.
Частые вопросы
Есть ли в 1С функция вроде ТекущийEmail()?
ИмяПользователя() и ПолноеИмяПользователя(). Адрес почты — прикладные данные конфигурации, его читают из справочника.Можно ли получить email пользователя в конфигурации без БСП?
Как получить почту внешнего пользователя?
ВнешниеПользователи и ссылаются на объект авторизации: контрагента или контактное лицо. Почту берут из контактной информации этого объекта. Ссылку на текущего вернёт Пользователи.АвторизованныйПользователь().Почему у пользователя два адреса и какой брать?
EmailПользователя, а остальные — только если основного нет. Так устроена сортировка в первом примере.