Статьи‎ > ‎

Автоматическая настройка почтового клиента Thunderbird в домене

Теме использования Mozilla Thunderbird в качестве корпоративного почтового клиента посвящено немало статей и заметок. В данной статье я хочу поделиться своим опытом внедрения Thunderbird на предприятии. Почему Thunderbird? - не всегда есть возможность использовать другие решения - например, в нашей сети практически отсутствуют компьютеры под управлением Microsoft Windows, а основная часть клиентских машин работает под управлением openSUSE. Можно использовать web-интерфейс почты, но для мобильных пользователей это неудобно - в условиях отсутствия или просто низкого качества доступа к интернету (в поезде, в гостинице, да где угодно за пределами комфортной зоны интернета) работа с почтой становится невозможна, а некоторым пользователям необходимо пусть не отправлять и получать письма, но хотя бы читать существующие и иметь возможность писать новые - в этой ситуации локальный почтовый клиент необходим, а из всего многообразия продуктов данной категории, наиболее универсальным всё же видится Thunderbird. Как и многим сотрудникам ИТ-подразделений, мне неоднократно приходилось настраивать учётные записи почты в почтовых клиентах пользователей, что вроде бы занимает лишь малую толику процесса настройки новой учётной записи на компьютере, но требует определённого времени и внимания, а после того, как я какое-то время проработал в сети на связке AD+Exchange+Outlook, мне захотелось получить столь же простой и удобный алгоритм настройки учётных записей почты и для других сред.

Итак, задача:
Обеспечить полностью автоматическую настройку основных параметров почтового клиента Thunderbird для пользователей, работающих как под Linux, так и под Windows, заходящих с доменными учётными записями. Исключить необходимость ручного ввода пароля в почтовом клиенте.

Исходная среда:
Домен развёрнут на "комбайне" zentyal community edition (бесплатная версия, без ограничений использования, но и без официальной поддержки) - к стати, очень рекомендую для предприятий, не использующих Windows Server и иные платные продукты. Из компонентов zentyal необходимы: Certification Authority, File Sharing and Domain Services, Mail Service, Users and Groups, по желанию можно ставить и любые другие, кроме "Groupware (Zarafa)", т.к. там используется другой механизм работы с почтой, хотя кому-то может больше понравиться и это решение. Домен (авторизация, адресная книга) реализован средствами SAMBA4, взаимодействие с почтой - dovecot и postfix (о их дополнительной настройке в zentyal, необходимой для корректной работы с GSSAPI-авторизацией на виртуальных доменах, будет отдельная статья).
В порядке эксперимента, проверялась работоспособность данного решения в чистом домене Windows - всё отрабатывает корректно, вот только до проверки работоспособности авторизации почты я не дошёл - нет готового шаблона почтового сервера, авторизующегося в Active Directory, но мне думается, что проблем возникнуть не должно, по крайней мере "Адресная книга" работает.
Клиентские машины под управлением openSUSE 12.3 и Windows XP/7, установлен Thunderbird (17.0.6); клиентские машины введены в "домен Windows"; пользователи заходят в компьютеры доменными учётными записями.

Основную концепцию настройки я взял из статьи на Хабре и комментариев к ней. Настройка автоматизации состоит из двух частей:

  1. Модификация установленного Thunderbird

  2. Настройка вспомогательного сервера, получающего дополнительные данные из ldap (AD)

На самом деле, вспомогательный сервер нужен лишь по той причине, что в используемом домене запрещён анонимный доступ к чтению свойств пользователей, а механизмов авторизации в ldap в скриптовом языке Mozilla на данный момент обнаружить не удалось.

Итак, что меняем в установленном на клиентские машины Thunderbird:
По пути установки Thunderbird (в моём случае это /usr/lib64/thunderbird или можно посмотреть в свойствах ярлыка) создаём файл serverconf.js (имя может быть произвольным, оно указывается в другом файле) следующего содержания:

if(getenv("USER") != "") {
    // *NIX environments
        var env_ename = getenv("USER");  // Следует учесть, что эта переменная имеет вид "DOMAIN\username", но нам нужен только username!
        env_name  = env_ename.substring(env_ename.lastIndexOf("\\")+1);
    } else {
        // Windows environments
        env_name    = getenv("USERNAME");
    };

lockPref("autoadmin.global_config_url", "http://configs.test.lan/tb/user/"+env_name);
// "configs.test.lan" - полное доменное имя нашего вспомогательного web-сервера
// на сервер передаётся имя текущего пользователя; почему столь необычно, разъясняется в статье на Хабре
lockPref("autoadmin.append_emailaddr", false);


Там же, в подкаталоге defaults/pref создаём файл addinit.js (или с любым другим именем) следующего содержания:

// Place this file in <thunderbird_install_dir>/defaults/pref
// For example: /usr/lib64/thunderbird/defaults/pref
pref("general.config.obscure_value",0);
pref("general.config.filename","serverconf.js");


Следует обратить особое внимание на используемые символы конца строки - в Windows обязательно надо использовать "DOS/Windows (CR+LF)", в то время как под Linux - только LF, иначе данные скрипты молча не запустятся; хотя данное условие "автоматически" выполняется при создании новых файлов и копировании в них содержимого через буфер с сайта, при копировании этих файлов между машинами, может возникнуть путаница. Для исправления символов конца строки удобно использовать встроенный редактор Far manager - в меню "Save as" там предусмотрены все три типа разметки (третья - Mac - CR).
Последнее, что неплохо бы сделать полезного, это разместить в подкаталоге defaults/profile (у меня его не было, так что его может понадобиться создать самостоятельно) файл cert8.db - в этом файле хранятся импортированные сертификаты - т.к. в моей среде используются защищённые SSL/TLS соединения, для которых используются самоподписанные сертификаты, без доверия будут выдаваться предупреждающие сообщения о подозрительных сертификатах, и чтобы избежать лишних вопросов пользователю, я вручную импортировал сертификат и ключ центра сертификации своего сервера, после чего все клиенты, имеющие его сертификат в хранилище "Доверенные центры сертификации", начинают доверять всем выпущенным им сертификатам. Если по пунктам, то делал следующее: скачал архив "Certification Authority Certificate" с файлами ca-cert.pem и ca-public-key.pem из раздела "Certification Authority" вэбморды zentyal, запустил свеженастроенный Thunderbird, зашёл в "Настройки - Настройки - Дополнительно - Сертификаты - Просмотр сертификатов" (перевод может несколько отличаться) и на вкладке "Центры сертификации" импортировал оба файла, при чём при импорте сертификата я не заморячиваясь поставил галочки всем пунктам доверия; закрыл Thunderbird и из его профиля (имеющего автогенерируемое имя и располагающегося в каталоге ~/.thunderbird или %APPDATA%\Thunderbird\Profiles) скопировал свежесозданный файл cert8.db.

Теперь настал черёд настройки вспомогательного сервера.
Установить apache, создать в нём virtualhost (при необходимости), подключить php и прочие прелести - здесь описывать не буду. Будем считать, что у нас есть настроенный web-сервер с mod_rewrite, понимающий php5, имеющий модуль php5-ldap (последнее - важно!), где есть каталог /tb/ в котором разрешен тот самый rewrite. В данном каталоге нам понадобится всего два файла, следующего содержания:
.htaccess

Options -Indexes
RewriteEngine on
RewriteBase /tb
RewriteRule ^user/(.*)                index.php?user=$1   [L]


Данный файл отвечает за преобразование запросов к серверу вида http://server/tb/user/username в http://server/tb/index.php?user=username - такое преобразование необходимо для совместимости со способом запроса конфигурации javascript языком Mozilla Thunderbird. Второй файл:
index.php

<?php
/**
 * скрипт генерации сценария автоматической настройки Thunderbird
 */

header ("Content-type: application/javascript; charset=utf-8");
if ($_GET['user']) {
     
$param['user']=$_GET['user'];  // Получаем значение переданного параметра user
 
} else {
     
die("We need at least your username!");  // Если параметр user не передан, выходим с уведомлением...
 
};

// Попытка прочитать параметры соединения с ldap из конфигурации dovecot
// данный блок является самопальным, но работающим парсером файлов конфигурации dovecot
// не будет работать, если apache работает в chroot-режиме, но на zentyal - функционирует
$ldapconf = '/etc/dovecot/dovecot-ldap.conf';
if (file_exists($ldapconf)) {
   
$ret = array();
   
$ldapstr = file($ldapconf,FILE_SKIP_EMPTY_LINES + FILE_IGNORE_NEW_LINES);
   
foreach($ldapstr as $line) {
     
$line = trim($line);
     
if(!$line || $line[0] == "#" || $line[0] == ";" || $line[0] == "[") continue; // пропускаем строки коментариев и секций
     
if(!strpos($line, '=')) continue; // пропускаем строки без названия ключа
     
$key = trim(substr($line,0,strpos($line, '='))); // название параметра
//      $val = html_entity_decode(trim(trim(substr($line,strpos($line, '=') + 1)),'"')); // значение параметра, без кавычек
     
$val = trim(trim(substr($line,strpos($line, '=') + 1)),'"'); // значение параметра, без кавычек
     
$ret[$key] = $val;}; // формируем массив параметров и их значений
   
$ldapuri = $ret['uris'];
   
$ldapdn  = $ret['dn'];
   
$ldappw  = $ret['dnpass'];
   
$ldapbas = $ret['base'];
 
} else {
   
die('Configuration file ' . $ldapconf . ' not found!');
};

// Назначаем параметры соединения с ldap-сервером, если полученные из dovecot не работают
// или требуется обращаться к другому ldap-серверу, как в zentyal 3.0
//$ldapuri = "ldap:///var/run/slapd/ldapi"; // адрес ldap-сервера
//$ldapdn = "cn=ldapbinduser,cn=users,dc=test,dc=lan"; // учётка пользователя, имеющего право читать из ldap
//$ldappw = "supersecurepassword"; // и его пароль - в данном случае, в открытом виде, т.к. по сети не передаётся
//$ldapbas = "cn=users,dc=test,dc=lan"; // ветвь, в которой будет производиться поиск данных пользователей
//$ldappar = "";

$ldapids = array("displayname","title","company","mail","telephonenumber","streetaddress","wwwhomepage"); // нам нужны только эти параметры

$ldapfilter = "(sAMAccountName=" . $param["user"] . ")"; // критерий поиска - в зависимости от структуры ldap
//$ldapfilter = "(uid=" . $param["user"] . ")"; // критерий поиска - в зависимости от структуры ldap
// В разных ситуациях может быть необходимо обращение к ldap на разных портах, или 389 по умолчанию
//$ldapconn = ldap_connect($ldapuri,3268)
//$ldapconn = ldap_connect($ldapuri,390)
$ldapconn = ldap_connect($ldapuri)
          or
die("Невозможно соединиться с $ldapuri");
ldap_set_option
($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option
($ldapconn, LDAP_OPT_REFERRALS, 0);
$ldapbind = ldap_bind($ldapconn, $ldapdn, $ldappw);
if (!$ldapbind) {
       
die("LDAP-привязка не удалась...");
   
};
$result = ldap_search($ldapconn,$ldapbas,$ldapfilter,$ldapids) or die ("Error in search query: ".ldap_error($ldapconn));
$lparam = ldap_get_entries($ldapconn,$result);
ldap_unbind
($ldapconn);
foreach($ldapids as $id) {
// присваиваем элементам массива $param соответствующие им значения, "экранируя" кавычки
 
$param[$id] = str_replace("\"","\\\"",$lparam[0][$id][0]);
 
};
// Выводим общий для всех пользователей заголовок:
$forcfg = file("templates/initvarprefs.cfg.head",FILE_IGNORE_NEW_LINES);
foreach($forcfg as $line) {
   
echo($line . PHP_EOL);
};
fclose($forcfg);
// Выводим параметры, полученные из ldap:
echo("var  var_name     = \"" . $param['user'] . "\";" . PHP_EOL);
echo("var  var_fullname = \"" . $param['displayname'] . "\";" . PHP_EOL);
echo("var  var_vacname  = \"" . $param['title'] . "\";" . PHP_EOL);
echo("var  var_orgname  = \"" . $param['company'] . "\";" . PHP_EOL);
echo("var  var_mailad   = \"" . $param['mail'] . "\";" . PHP_EOL);
echo("var  var_phone    = \"" . $param['telephonenumber'] . "\";" . PHP_EOL);
echo("var  var_orgadr   = \"" . $param['streetaddress'] . "\";" . PHP_EOL);
echo("var  var_site     = \"" . $param['wwwhomepage'] . "\";" . PHP_EOL);
// Эта переменная формируется одной из последних, поэтому осталась в php
echo("var  var_userdn   = \"cn=\" + var_name + \",\" + var_usersdn;" . PHP_EOL);

$forcfg = file("templates/initvarprefs.cfg.foot",FILE_IGNORE_NEW_LINES);
foreach($forcfg as $line) {
   
echo($line . PHP_EOL);
};
fclose($forcfg);
?>


Как можно увидеть из листинга скрипта генерации конфигурации, практически никаких настроек данный скрипт не отдаёт, а лишь заполняет некоторые переменные для скрипта автоконфигурации. Почему используется чтение параметров подключения к ldap-серверу из файла настроек dovecot, думаю, понятно, но если такой подход нас не устраивает, то можно присвоить эти параметры в теле скрипта, не забыв создать соответствующего пользователя, с правом чтения данных из ldap.
Собственно само присвоение параметров вынесено в два внешних шаблона - initvarprefs.cfg.head и initvarprefs.cfg.foot, которые я положил в подкаталог templates итак, файл, начинающий скрипт:

/* Этот файл настраивает начальные параметры пользователя
 * Пожалуйста, проверьте работоспособность перед использованием!
 *
 * Обратите внимание на присвоение значений переменным:
 *  var_name - логин пользователя (для GSSAPI-авторизации)
 *  var_fullname - полное имя пользователя
 *  var_vacname - название должности (для подписи)
 *  var_orgname - название организации (для подписи)
 *  var_mailad - email пользователя
 *  var_phone - контактный телефон (для подписи)
 *  var_orgadr - адрес организации (для подписи)
 *  var_site - адрес вэб-сайта (для подписи)
 *  var_domname - почтовый домен пользователя
 *  var_realm - название пространства авторизации (Kerberos realm)
 *  var_userdn - LDAP DN пользователя для GSSAPI-авторизации в LDAP
 *  var_ldapuri - uri сервера LDAP для получения адресной книги
 *  var_mailhost - FQDN имя почтового сервера (в принципе, может быть IP-адресом)
 *  var_gsshost - FQDN имя почтового сервера, пригодное для авторизации GSSAPI/Kerberos
 */

try {
var  var_domname  = "@test.lan";
var  var_realm    = "@TEST.LAN";
var  var_mailhost = "zent.test.lan";
var  var_gsshost  = "zent.test.lan";
var  var_usersdn  = "cn=users,dc=test,dc=lan";
var  var_ldapuri  = "ldap://" + var_gsshost + "/" + var_usersdn + "??sub?(objectclass=person)";


Внезапно оказалось, что первая пустая строка в этом файле необходима и должна быть пустой, иначе скрипт не выполнялся - я не смог найти этому разумных объяснений.

Второй файл:

// Настройки для Lighting:
defaultPref("calendar.timezone.local", "Europe/Moscow");
defaultPref("calendar.ui.version", 1);
defaultPref("calendar.view.dayendhour", 18);  // Рабочий день заканчивается в 6:00 pm aka 18:00
defaultPref("calendar.view.daystarthour", 9);  // ...а начинается в 9:00 (am)
defaultPref("calendar.week.start", 1);  // Начинаем неделю с понедельника
// Настройки адресной книги в LDAP:
defaultPref("ldap_2.servers.Domainadressbook.auth.dn", var_userdn);
defaultPref("ldap_2.servers.Domainadressbook.auth.saslmech", "GSSAPI");
defaultPref("ldap_2.servers.Domainadressbook.description", "Domain adressbook");
defaultPref("ldap_2.servers.Domainadressbook.filename", "ldap.mab");
defaultPref("ldap_2.servers.Domainadressbook.maxHits", 500);
defaultPref("ldap_2.servers.Domainadressbook.uri", var_ldapuri);
defaultPref("ldap_2.autoComplete.directoryServer", "ldap_2.servers.Domainadressbook"); // разрешаем автоподстановку из ldap
defaultPref("ldap_2.autoComplete.useDirectory", true);
// Настройки аккаунтов и хранилищ почты:
defaultPref("mail.account.account1.identities", "id1");  // Нужна
defaultPref("mail.account.account1.server", "server1");  // Нужна
defaultPref("mail.account.account2.server", "server2");  // Нужна
defaultPref("mail.account.lastKey", 2);  // Количество активных аккаунтов
defaultPref("mail.accountmanager.accounts", "account1,account2");  // Нужна
defaultPref("mail.accountmanager.defaultaccount", "account1");  // Нужна
defaultPref("mail.accountmanager.localfoldersserver", "server2");  // Нужна
defaultPref("mail.identity.id1.fullName", var_fullname);  // Отображаемое имя для 1-го аккаунта
// Генерируем текст подписи
defaultPref("mail.identity.id1.htmlSigText", "С уважением,\n" + var_vacname + "\n" + var_orgname + "\n" + var_fullname + " \<" + var_mailad + "\> \nТел.:" + var_phone +"\n" + var_orgadr + "\n" + var_site);
defaultPref("mail.identity.id1.organization", var_orgname);  // Отображаемое название организации для 1-го аккаунта
defaultPref("mail.identity.id1.smtpServer", "smtp1");  // Сервер исходящей почты для 1-го аккаунта
defaultPref("mail.identity.id1.useremail", var_mailad);  // Адрес E-mail, используемый при отправке писем
// Настройки папок хранилища
defaultPref("mail.identity.id1.draft_folder", "imap://" + var_name + "@" + var_mailhost + "/Drafts");  // Черновики
defaultPref("mail.identity.id1.fcc_folder", "imap://" + var_name + "@" + var_mailhost + "/Sent");  // Отправленные
defaultPref("mail.identity.id1.stationery_folder", "imap://" + var_name + "@" + var_mailhost + "/Templates");  // Шаблоны
defaultPref("mail.identity.id1.valid", true);  // Нужна
defaultPref("mail.openMessageBehavior.version", 1);  // Не знаю =)
defaultPref("mail.rights.version", 1);  // Выключаем rights notification
defaultPref("toolkit.telemetry.prompted", true);  // Выключаем запрос об отправке отзывов
// Можно поменять тип хранилища сообщений - по умолчанию "@mozilla.org/msgstore/berkeleystore;1" и имеет ограничение в 4ГиБ
// тип хранилища maildirstore ещё не поддерживается официально и имеет ряд недоработок
// defaultPref("mail.server.server1.storeContractID", "@mozilla.org/msgstore/maildirstore;1");
// defaultPref("mail.server.server2.storeContractID", "@mozilla.org/msgstore/maildirstore;1");

// Настройки работы с сервером IMAP
defaultPref("mail.server.server1.authMethod", 5);  // Тип авторизации - GSSAPI/Kerberos
defaultPref("mail.server.server1.spamActionTargetFolder", "imap://" + var_name + "@" + var_mailhost + "/Spam");  // Спам
defaultPref("mail.server.server1.moveOnSpam", true);
defaultPref("mail.server.server1.moveTargetMode", 1);
defaultPref("mail.server.server1.cacheCapa.acl", false);
defaultPref("mail.server.server1.cacheCapa.quota", true);
defaultPref("mail.server.server1.check_new_mail", true);
//defaultPref("mail.server.server1.cleanupBodies", false);
//defaultPref("mail.server.server1.daysToKeepBodies", 1);
//defaultPref("mail.server.server1.daysToKeepHdrs", 1);
//defaultPref("mail.server.server1.downloadByDate", false);
//defaultPref("mail.server.server1.downloadUnreadOnly", false);
defaultPref("mail.server.server1.hostname", var_mailhost);  // FQDN сервера IMAP
//defaultPref("mail.server.server1.keepUnreadOnly", false);
defaultPref("mail.server.server1.login_at_startup", true);
//defaultPref("mail.server.server1.max_cached_connections", 5);
defaultPref("mail.server.server1.name", var_fullname);   // Название аккаунта
//defaultPref("mail.server.server1.namespace.personal", "\"\"");
//defaultPref("mail.server.server1.numHdrsToKeep", 2000);
defaultPref("mail.server.server1.port", 993);
defaultPref("mail.server.server1.realhostname", var_gsshost);   // Имя сервера, принимаемое GSSAPI/Kerberos (как в выводе 'klist')
defaultPref("mail.server.server1.realuserName", var_name + var_realm);  // Имя пользователя для авторизации GSSAPI/Kerberos
defaultPref("mail.server.server1.socketType", 3);  // SSL/TLS
defaultPref("mail.server.server1.timeout", 29);
defaultPref("mail.server.server1.type", "imap");
defaultPref("mail.server.server1.userName", var_name);  // Logon username
// Настройки исходящей почты:
defaultPref("mail.smtpserver.smtp1.authMethod", 5);  // GSSAPI/Kerberos authentication
defaultPref("mail.smtpserver.smtp1.hostname", var_gsshost);
defaultPref("mail.smtpserver.smtp1.port", 587);
defaultPref("mail.smtpserver.smtp1.try_ssl", 2);
defaultPref("mail.smtpserver.smtp1.username", var_name + var_realm);
defaultPref("mail.smtpservers", "smtp1");

defaultPref("mail.server.server2.directory-rel", "[ProfD]Mail/Local Folders");
defaultPref("mail.server.server2.hostname", "Local Folders");
defaultPref("mail.server.server2.name", "Локальные папки");
defaultPref("mail.server.server2.spamActionTargetAccount", "mailbox://nobody@Local%20Folders");
defaultPref("mail.server.server2.type", "none");
defaultPref("mail.server.server2.userName", "nobody");

defaultPref("mail.startup.enabledMailCheckOnce", true);
defaultPref("mail.ui-rdf.version", 5);
defaultPref("mail.warn_on_send_accel_key", false);  // Отключаем предупреждение при отправке писем по Ctrl+Enter

} catch(e) {
    displayError("defaultPref", e);
}


Для начала стоит проверить корректность работы нашего сервера, отдающего настройки Thunderbird - заходим по адресу http://_servername_or_address_/tb/user/testuser - должно отдать настройки для пользователя "testuser", если видим пустой экран, то надо пойти в логи апача и посмотреть на что он жалуется; при правильной работе должно выдать слитно содержимое файлов *.head и *.foot, поместив между ними что-то типа такого:

...
var  var_name     = "testuser";
var  var_fullname = "Максим Федоров";
var  var_vacname  = "Старший помощник младшего дворника";
var  var_orgname  = "ООО \"Наше всё\"";
var  var_mailad   = "testuser@test.lan";
var  var_phone    = "+7(495)221-10-28";
var  var_orgadr   = "Бутырский вал, 17";
var  var_site     = "http://www.ya.ru/";
var  var_userdn   = "cn=" + var_name + "," + var_usersdn;
...


Если пользователь, переданный в url, не найден, упомянутый кусок кода будет выглядеть так:

...
var  var_name     = "testuser";
var  var_fullname = "";
var  var_vacname  = "";
var  var_orgname  = "";
var  var_mailad   = "";
var  var_phone    = "";
var  var_orgadr   = "";
var  var_site     = "";
var  var_userdn   = "cn=" + var_name + "," + var_usersdn;
...


Соответственно, при запуске Thunderbird настройка аккаунта будет произведена, но все "красивости" типа полное имя пользователя, название почтового аккаунта, подпись и т.п. будут заполнены пустотой - это возможно, если пользователь отсутствует в dn поиска нашего скрипта (например, если "Users" в переменной $ldapbas у нас имеет тип не "cn" - "контейнер", а "ou" - "подразделение", или искомого пользователя по организационным причинам переместили в другой ou, за пределами указанного в $ldapbas).
Если при обращении к web-серверу получаем сообщение:

Not Found

The requested URL /tb/user/testusername was not found on this server.
Apache/2.2.22 (Ubuntu) Server at 192.168.122.101 Port 80


Значит, не работает mod_rewrite или неверно настроен виртуальный сервер или виртуальный каталог, к которому производится обращение.
По собственному опыту и по результатам чтения тематических форумов, наибольшее число ошибок приходится на взаимодействие с ldap-сервером - либо мы не получили корректных настроек из файла dovecot (в этом случае следует удалить/закоментировать блок чтения настроек из конфига dovecot и использовать блок ручного присвоения настроек), либо на используемом сервере запрещена работа указанному пользователю. Если вроде бы всё должно работать, но в логах продолжается ругань на подключение к ldap, попробуйте подключиться к ldap-серверу альтернативными методами - с помощью команды ldapsearch, например, используя введённые данные. Вторая весьма распространённая засада - использование в файлах скриптов настройки Thunderbird символов конца строки в стиле DOS/Windows (CR+LF), хотя вроде бы средствами PHP, в приведённом примере эта проблема "обойдена". Да, и не знаю почему, но у меня на одной тестовой машине скрипт, полученный от вспомогательного сервера не выполнялся, если он не начинался с пустой строки, ну или по крайней мере, если первая строка была комментарием в стиле "/* ".
На самом деле, содержание файлов-шаблонов конфигурации Thunderbird можно модифицировать по своему усмотрению, добавляя/удаляя нужные/лишние настройки - для этого достаточно любыми доступными способами внести необходимые изменения в настройки работающего почтового клиента, а затем скопировать необходимые параметры из файла prefs.js, хранящегося в профиле Thunderbird (предварительно закрыв почту, для сохранения файла конфигурации).
В приведённом примере, все настраиваемые параметры оставлены доступными для изменения пользователем через графический интерфейс Thunderbird - это сделано для возможности ручной корректировки настроек пользователями, в соответствии со своими личными предпочтениями или требованиями обстоятельств; если необходимо часть параметров заблокировать от изменения пользователем, в шаблонах конфигурации следует вместо инструкции defaultPref использовать lockPref с тем же синтаксисом.

После получения настроек, Thunderbird должен подключиться к почтовому серверу с использованием GSSAPI. В Linux наличие такой попытки можно обнаружить, введя команду klist:

TEST\testuser@linux-7r77:~> klist
Ticket cache: FILE:/tmp/krb5cc_10002
Default principal: testuser@TEST.LAN

Valid starting     Expires            Service principal
06/27/13 12:10:09  06/27/13 22:10:09  krbtgt/TEST.LAN@TEST.LAN
        renew until 07/04/13 12:10:09
06/27/13 12:10:09  06/27/13 22:10:09  LINUX-7R77$@TEST.LAN
        renew until 07/04/13 12:10:09
06/27/13 12:10:35  06/27/13 22:10:09  imap/zent.test.lan@TEST.LAN
        renew until 07/04/13 12:10:09
06/27/13 13:14:45  06/27/13 22:10:09  ldap/zent.test.lan@TEST.LAN
        renew until 07/04/13 12:10:09
06/27/13 13:19:24  06/27/13 22:10:09  smtp/zent.test.lan@TEST.LAN
        renew until 07/04/13 12:10:09
TEST\testuser@linux-7r77:~>


Первые два тикета в приведённом примере - тикеты авторизации системы в домене, а вот последние три - это как раз используемые Thunderbird тикеты авторизации на серверах. Формат наименования в данном случае service/server@realm, где "service" - сервис, на который получена авторизация Kerberos/GSSAPI, "server" - имя сервера, по которому получена авторизация, "realm" - пространство Kerberos, в котором получена авторизация, как правило, совпадает с полным именем домена, и указывается заглавными буквами.

Comments