вторник, 3 мая 2011 г.

Ява головного мозга. Массовый сбор вложений из электронной почте по imap-протоколу

Вы пишете письма? Разумеется, речь идет об электронной корреспонденции ;-) Когда-то я не понимал, зачем сегодня, во время обилия интернет-сервисов для общения пользоваться электронной почтой. А теперь могу без преувеличения сказать, что это одно из гениальнейших изобретений в истории IT. Главное, правильно уметь ее готовить! Поэтому, поговорим сегодня о готовке, жарке, варке и … Хм, пожалуй я увлекся - сказывается позитивное настроение после корпоративной вечеринки ;-) Сегодня речь пойдет о массовой обработке почтовых вложений, а именно, о сборе и обработке фотографий из почтовых вложений с почтового сервера по протоколу imap.
Мне часто пишут письма с фотографиями. Все они аккуратно раскладываются по imap-папочкам моего gmail-аккаунта. Иногда есть необходимость собрать все эти фото и сделать из них альбом. Делать это вручную - почти нереально. К примеру, от человека “Н” у меня 250 фото - это порядка 100 писем! Вы же понимаете, что загружать, переименовывать с включением даты - труд явно предназначенный для машин. Поэтому, одним зимним вечером я решил написать для себя скрипт на java, осуществляющий вышеописанную задачу.
Важно заметить, что я использую протокол imap. Его основное преимущество - это работа с почтовым деревом папок. Скрипт, работающий с моим почтовым ящиком на gmail оказался небольшим - менее 100 строк и занял не более 10 минут, включая время для освоения библиотеки javamail. Запускаю - сыплются exception’ы при обработке вложений. Для отладки добавляю их игнорирование и смотрю, на результат выгрузки фото. Результат вводит в ступор - у каждой фотографии в конце не хватает последовательности байт длиной от 10 байт, до 20 кБайт! Одним словом, при чтении потока файла вылетает исключение при декодировании base64-датаграммы:
Exception in thread "main" com.sun.mail.util.DecodingException: BASE64Decoder: Error in encoded stream: needed 4 valid base64 characters but only got 1 before EOF, the 10 most recent characters were: "Q3w5ilxj2P"
Убив почти час времени на попытку осознать, откуда прилетает ко мне черенок от граблей, я натыкаюсь на “A list of the known limitations, bugs, issues” библиотеки javamail, в которм есть такой неприметный шестой пункт:
Certain IMAP servers do not implement the IMAP Partial FETCH functionality properly. This problem typically manifests as corrupt email attachments when downloading large messages from the IMAP server. To workaround this server bug, set the "mail.imap.partialfetch" property to false. You'll have to set this property in the Properties object that you provide to your Session.
Я конечно все понимаю, бывают баги, бывают несовместимости. Но почему "mail.imap.partialfetch" по умолчанию включен! Этот параметр почти ни один почтовый imap-сервер не поддерживает! Где логика?!
Самое неприятное, что информации по этой проблеме в сети довольно мало. А на тот момент, когда я искал - вообще почти не было. Люди жаловались на ошибку, но почти никто не знал ответа на вопрос. Решения я нашел в малоприметной группе google (Google Groups).
Поэтому, друзья мои, если вам доведется работать с вложениями по протоколу imap - пожалейте свои нервы, проверьте опцию "mail.imap.partialfetch" ;-) А раз сегодня речь пошла о нелогичностях в библиотеках, то ответьте на вопрос: “Какие ляпы, странности, нелогичности встречали вы на своим IT-пути?”.

P.S.: кому не хочется изобретать велосипед, прикладываю написанный на коленке скрипт.  И не нужно мне говорить, что побайтовая запись - это медленно! Мне хватило, если вам понадобиться - напишите буферизированную ;-)

Комментариев нет:

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