Среди всех причуд биллинга есть та, от которой я все никак не могу отделаться. Сия причуда инспирирована самой структурой биллинга. Что обычно делают, когда нужно выставить счета всем абонентам? Все верно! Нажимают в веб-интерфейсе кнопку "Печать" - и через несколько минут (часов, дней - в зависимости от количества абонентов) забирают результат из самого большого конторского принтера. В данном случае простейшая операция обернулась огромным количеством заморочек.
Поскольку веб-интерфейс расположен в 4.000 километрах от ближайшего нашего принтера - пришлось придумать какое-то нестандартное решение. В документации к биллинговой системе был почти готовый вариант. Поднять почтовик (рассматривался sendmail), создать ящик специально для писем от ядра системы, настроить CUPS с кучей скриптов, затем указать созданный ящик в веб-интерфейсе биллинга - и вуаля! Одной кнопкой можно распечатать все нужные документы на принтере, находящемся хоть за тридевять земель. Почтовиков у нас было на тот момент два. Я уже начал было реализовывать вариант с CUPS - как был случайно обнаружен более оптимальный способ настройки сетевой печати для наших нужд.
Биллинг высылал документы по электронной почте на наш почтовый сервер в виде вложения в формате PDF. Раз в пять минут по заданию в cron запускался скрипт, который извлекал из сообщений все вложения в формате PDF. Для таких целей я использовал пакет uudeview. Полученный набор актов и счетов нужно было как-то отправлять на принтер. В пакете ghostscript я обнаружил утилиту pdf2ps, которая конвертировала документы PDF в формат PostScript, понятный любому более-менее продвинутому принтеру. Именно эту утилиту я применял к каждому PDF-файлу. Далее я с помощью штатного средства печати FreeBSD под названием lpr отправлял PostScript на принтеры. Вот такая незатейливая схема, которая, разумеется, была намного проще штатного варианта с CUPS/procmail.
Осталось только найти подходящий для печати принтер. Первой жертвой был HP LaserJet 1220 с сервером печати JetDirect 175x. Он соглашался принимать акты и счета, но вот со счет-фактурой вышел облом. Несмотря на то, что счета-фактуры были в альбомной ориентации - принтер пытался печатать их в книжной, в результате чего получались две на треть заполненные табличными данными страницы :). Можно было, конечно, изобрести костыль (в ghostscript для костылей есть немало средств), но полумеры меня не интересовали. HP LaserJet 1220 был оставлен в покое.
Следующей жертвой адских техногенных экспериментов стал HP LaserJet 3055. Это уже более серьезный комбайн со своим собственным принт-сервером, поэтому я не без оснований ожидал от него более адекватного поведения. И 3055 не разочаровал! Он без проблем распознал присланный ему PostScript. Он распечатал счет-фактуру именно так, как требовалось - на одном листе, в альбомной ориентации. И когда принтер был запущен в промышленную эксплуатацию - пришлось и его оставить в покое. Потому что при попытке отправить на печать жалкую сотню документов он вешался намертво - и никакие ухищрения, помимо отключения питания, не возвращали его к жизни. Обидно. А так все хорошо начиналось!
Было принято решение заюзать тяжелую артиллерию. Мы покусились на святую святых конторы - принтер HP LaserJet 5200. Гора оперативной памяти, огромные картриджи, нереальные скоростные и нагрузочные характеристики намекали на то, что задача по печати будет решена не только для реалий сегодняшнего дня, но и с большим запасом на будущее. Принтер без каких-либо проблем справился со всеми тестами и выдержал первую боевую распечатку из пары сотен документов. Был взят на вооружение.
Казалось бы, что все довольны и счастливы, получили желаемое, однако счастье длилось недолго. Фактически этот принтер был похищен у одного из самых капризных отделов нашей конторы. И, разумеется, этот отдел не хотел мириться с похищением. Пусть даже на один час в месяц. Отдел оказался настолько крут, что продавил решение о покупке отдельного принтера для реализации печати документов из биллинга. Но бюджет оказался примерно в 4 раза меньше стоимости того же HP LaserJet 5200. Шеф предложил мне посмотреть характеристики принтера Kyocera FS-1035MFP. Я купился на прямую печать PDF-файлов. Разве можно было отказаться от возможности упростить написанный ранее скрипт? :)
В-общем, железка была приобретена. Первые результаты экспериментов были неутешительными. Стандартный lpr вгонял принтер в состояние ступора, из которого железку можно было вывести лишь нажатием пары кнопок на пульте управления. В лучшем случае он печатал краказябры, причем я использовал и PostScript, и PDF. Заявленная прямая печать PDF на проверку оказалась возможностью подключить к принтеру флэшку и распечатать расположенные на ней PDF-файлы. Ситуация была совершенно безнадежной.
Спустя полтора месяца я случайно заглянул в веб-интерфейс этой киосеры - и увидел там настройки POP3. "На кой черт принтеру нужен POP3?" - подумал я. SMTP понятно - чтобы присылать нашей техподдержке информацию о том, что пора бы заправить картридж тонером или вытащить замятую бумагу. Но POP3 мог использоваться только для одной цели - для печати присланных принтеру материалов. Для проверки была создана тестовая учетка, я отправил на нее небольшой PDF-документ - и через пять минут он лежал в киосере в распечатанном виде :o.
Когда была проверена повторяемость результатов на разных PDF-ках, принтеру направили несколько тестовых документов из биллинговой системы - и я с ужасом обнаружил, что они не печатаются. Принтер показывает присланные письма в своих заданиях, но при этом утверждает, что вложений в письмах нет. Расследование показало грубейшее нарушение принтером RFC2183 (The Content-Disposition Header Field). Например, если в сообщении содержится вот такое вложение: