Библиотека для работы с MIME
Для написания некого почтового фильтра на Си понадобилась библиотека для работы с MIME-заголовками. Почтовый фильтр должен уметь вытаскивать из письма список имён вложенных в него файлов. Фильтр предполагался многопоточным(multithreaded) и потому библиотека должна была быть дружественна к многопоточному использованию ().
Как оказалось — это не простая задача. Большинство найденных библиотек используют «глобальные области» для хранения разобранных MIME-структур. Отведённое место хранения данных всех потоков — едино. И при параллельной работе потоков происходит перемешивание данных. В лучшем случае приложение работает не правильно, в худшем — падает при очищении памяти одного потока из другого.
Исследованию подверглись библиотеки проектов: altermime, libmime, mimedecode, minimime, renattach, ripmime, uudeview. Для моих целей все эти библиотеки не подошли, и тщательных тестов я не проводил, но пару слов хочу сказать о двух из них:
- ripmime — мне показалось, что эта библиотека наиболее отвечает современным представлениям в работе с MIME. Регулярно выходят обновления и фиксы.
- uudeview (uulib) — мне понравилось за простоту написания своих приложений на её базе. Открыл файл, сделал UULoadFile () и можно работать. Например, что бы получить список вложений в письмо, надо сделать цикл по UUGetFileListItem ().
Пытливый читатель может задать вопрос: а зачем вообще библиотека, почему бы не использовать регулярные выражения для поиска и вычленения имён вложений? Да, такая идея была и она даже была реализована. Но с ней оказалось больше проблем. Вариантов того, как в письмо может быть вложен файл — достаточно много. И не все они просты. Я нашёл интересный ресурс (), который приводит примеры HTTP заголовка Content-Disposition и RFC 2231/2047. Там же там присутствует сравнение поддержки их броузерами — это тоже интересно, но уже оффтопик для моей статьи. :)
Например такие не простые примеры:
Заголовок: Content-Disposition: attachment; filename*1="foo."; filename*2="html" Значение: 'attachment' (параметр filename* игнорируем, потому что отсутствует filename*0)
Заголовок: Content-Disposition: attachment; filename*1="bar"; filename*0="foo" Значение: 'attachment', filename="foobar"
Вариантов много и всё это реализовывать самому не очень хочется, потому и был затеян поиск библиотеки.
И заветная библиотека нашлась — это . На её домашней странице есть документация (хотя, кажется, не совсем свежая) по доступным функциям. И, о чудо, она безопасная для работы в многопоточном режиме. В данный момент её поддерживает Sergey Poznyakoff, который достаточно оперативно отвечает в списке рассылки, исправляет проблемы и дополняет функционал. В данный момент я использую библиотеки, потому что там реализована поддержка RFC 2231/2047. Так же весьма полезными оказались примеры, которые входят в дистрибутив (./examples).
В результате мой фильтр написан, работает и проходит тестовые испытания. Пока нареканий на mailutils нет.









Оставить комментарий