Как стать автором
Обновить

Комментарии 56

Вопрос, а какой клиент с Вашей точки зрения вы рекомендуете?
я сейчас пользуюсь rhu8nderbird и многим недоволен, хочу чего-то «быстрее», что бы вы порекомендовали?
А какая платформа: windows/linux/mac os x, что именно не устраивает в скорости? Я лично imap-ом на android-е в основном пользуюсь, использую aquamail.
windows, thunderbird
на ящиках свыше 10к писем очень медленно работает :)
Хоть я сам лично и не фанат, но очень многие хвалят outlook :) Он вроде бы нормально работает с большой базой писем. Еще как вариант есть the bat и opera. Друзья использовали the bat + imap на довольно больших аккаунтах.

Для меня идеален был бы десктопный клиент с моделью работы мобильных клиентов: не качать ничего лишнего, всякие аттачи и картинки fetch-ить по запросу. Особенно это было бы актуально в случае слабого internet-канала. К сожалению, я таких клиентов не встречал, поэтому для десктопа использую веб-интерфейс. Он примерно соответствует моим требованиям не качать ничего лишнего.
Можно настроить, качать только заголовки писем, почти в любом клиенте.
Я тоже письмо не полностью качаю. У меня стоит SSD HDD и я просто экономию место.
Ну заголовки — это тоже может быть достаточно много, особенно, в случае, если это автогенеренные текстовые письма. А заголовки 100-200 тыс писем — это уже прилично данных само по себе. Их надо уметь прилично индексировать, с чем не всегда клиенты справляются.

Мобильные клиенты такой кучи информации стараются не хранить, а получают только последние сообщения, что мне и нравится.
Хорошая статья, систематизировали все проблемы imap.
Витя, супер, респект за IMAP. Хорошая работа!
Спасибо, очень интересно! Лишний раз подтверждает, что на практике все «немного не так», как написано в RFC.
Не всегда, а только для неудачных протоколов.
Вопрос не совсем по теме, но весьма меня волнующий.
mime вложений, разсширение, magic проверяются у вас уже или пока нет?
Помню, полгода назад с этим были проблемы. У gmail не было.
К сожалению, не совсем понял, о чем речь. Плюс, полгода назад у нас имап, насколько помню, еще был только на внутреннем тестовом сервере и проблем там было море :)

Если речь об ответах BODY/BODYSTRUCTURE, то, согласно RFC, мы там возвращаем все поля из письма, которые клиенты могут использовать для работы с вложениями: content-id, content-type с полями charset и name, content-disposition с полем filename.
Писали мы клиент, который отправляет пользователю счет (с инн \ кпп, пасьянсом и барышнями) формате pdf. Использовали для сего действия gen_smtp.

Тестовые письма

Все три письма идентичны и все с вложениями. Только для последнего (первого в списке) был указан параметр application=pdf. Content-Type во всех случаях был application/pdf.
Что конкретно, мы отправлялось, не проверяли.
Если, любопытно, могу и покопаться.
Такая проблема была (и есть?) только у mail.ru.

Извиняюсь за офтоп (хотя вся ветка — оффтоп),
но на всякий пожарный приведу код:
mail(         {FromName, FromEmail}, 
                {ToName, ToEmail}, 
                Subject, 
                Body, 
                {AttachName, AttachBinary}
) -> 
    Email = {<<"multipart">>, <<"mixed">>, [
                {<<"From">>, mmh_person(FromName, FromEmail)},
                {<<"To">>, mmh_person(ToName, ToEmail)},
                {<<"Subject">>, list_to_binary(Subject)}],
            [],
            [
             %% Тело письма
             {<<"text">>,<<"plain">>, [], [], list_to_binary(Body)},
             %% Аттачменты(PDF) 
             {<<"application">>,<<"pdf">>,
                [{<<"Content-Type">>,<<"application/pdf">>},
                 {<<"Content-Transfer-Encoding">>,<<"base64">>}],
                [
                 {<<"content-type-params">>,
                [{<<"name">>, list_to_binary(AttachName)}],
                [{<<"x-unix-mode">>,<<"0644">>}]},
                {<<"disposition">>,<<"attachment">>},
                {<<"disposition-params">>,[{<<"filename">>, 
                                list_to_binary(AttachName)}]}],
                AttachBinary}
            ]},
    gen_smtp_client:send(
        {
            FromEmail,
            [ToEmail],
            mimemail:encode(Email)
        },  ?SYS_MAIL_OPTIONS
    ).

Ага, т.е. речь все-таки об SMTP сервере. Я слишком плохо знаком с erlang-ом, чтобы суметь легко попробовать этот пример. Не могли бы вы сгенерить тела этих двух писем (с глюком и без), положить их в zip-архив и прислать мне на v.starodub {собака} corp.mail.ru? Мы разберемся, где именно глюк — в телах писем, или же в SMTP/веб-интерефейсе, если у нас — то с радостью починим.

Как я понимаю, генерацию производит вызов mimemail:encode(), а gen_smtp занимается уже отправкой?
SMTP сервере.
— Клиенте.
Gen_smtp занимается отправкой, но только в качестве клиента. Отправкой занимается sendmail (как я понимаю), который находится удаленно.
Остальное, вы поняли правильно.

Возможно, как верно подметил ниже Макс, это как раз пример такого «чу́дного клиента».
Попробую сделать что вы сказали.
Думаю, что тут вряд ли дело в клиенте, т.к. SMTP — очень агностичный протокол по отношению к телу письма, smtp-клиенту редко нужно уметь парсить mime письма дальше нескольких хэдеров и вообще разбираться, что там внутри. Исключение составляет только разве что binary extension.

Нужно смотреть в тело письма.
Если я воспроизвел именно ту ошибку о которой говорил, то я немного соврал. Уж слишком давно это было. Да и во общем, вроде уже проблему решили, не актуально.

Проболема была в multipart/alternative. Т.о., с вашей стороны все было сделано, формально правильно. Однако, поведение, интерфейса почты
— странно, и несколько не предсказуемо.

Пока пытался воспроизвести, эту проблему я нашел, еще несколько интересных особенностей. Сервисы на которых, я тестировал почту были выбраны от балды (никаких предрассудков и предрасположенностей не имею), просто нужно было с чем-то сравнивать.

  1. Если указать, multipart не mixed, a alternative, в mail.ru вложение приходит то в гриде просмотра почты не отображается, что есть вложение. У mail.yandex.ru показывает, что вложение есть, но в письма вложения вообще нет (скачивать нечего). То, что вложение есть показывается не сразу после получения письма, а если немного подождать. У gmail.сom все ок.
    Если я действительно, воспроизвел ту самую проблему, понятно, почему у mail.yandex.ru она не была замечена. Не факт, что внутрь письма заглядывали, когда тестировали полгода назад.

  2. Была замечена ошибка у mail.yandex.ru. Если отправлять письмо без, Content-Transfer-Encoding: base64 то в гриде просмотра почты не отображается, что есть вложение. Всего скорее проблемы в интерфейсе. Потому что поcле просмотра письма значок аттача появляется. У mail.ru все ок. У gmail.сom все ок.
  3. Если не указать disposition-params у mail.ru, то нет аттача в гриде просмотра почты. Если открыть само письмо, то аттач есть (Untitled.pdf вместо имени). Проблема всего скорее только в интерфейсе, ибо thunderbird этот аттач видит и до открытия письма. У mail.yandex.ru в этом случае вообще не показывает аттача. У gmail.сom все ок, но вложение соответсвенно называется noname (без расширения).
  4. Была замечена ошибка у mail.yandex.ru Если отправлять письмо без, content-type-params, то в гриде просмотра почты не отображается, что есть вложение. У mail.ru все ок. У gmail.сom все ок.


Несколько урезанные версии писем на которых тестировалось:
gist.github.com/b5bb40d982604b40b5b7
Полные версии продублировал на почту.
Молодцы!

Полагаю, что вам ещё год-два знакомиться с разными диалектами чудных клиентов, которые шлют команды именно в таком порядке, в котором вы уж точно никак не рассчитывали, но вы и это разберете =)

Насколько вам пришлось менять само базовое хранилище писем? К нему централизованный доступ или вы запускаете на каждом сервере со стораджами свой IMAP сервер?
Спасибо :)

К хранилищу пришлось прикрутить imap-ные uid-ы и uidvalidity, а также их обновление в случае модификаций писем. Это теоретически несложно, но нужно было быть аккуратным и поправить достаточное кол-во кода. Также там была прикручена пара оптимизаций для ускорения частичной отдачи письма в RFC-формате, это не было нужно pop3 и веб-интерфейсу.

Вообще, одна из целей написания собственного сервера — не менять сильно хранилище, т.к. переиндексировать все письма — очень «дорого», в наших объемах это может занять до полугода. Мы обошлись только довольно «дешевой» раздачей uid-ов, которую мы делаем при первом доступе по imap к ящику.

Хранилище у нас на отдельных серверах, имап является таким же клиентом хранилища, как и pop3, smtp и веб-интерфес. Они все дергают один API по одному протоколу.

детский сад :)
В Outlook 2013 добавили RFC6154 XLIST
>Уже некоторое время IMAP работает в Почте Mail.Ru в полную силу
Гмайл IMAP с 2008 г.
Яндекс IMAP с 2009 г.
Про IMAP на Mail.Ru в 2012 смешно читать, как и о почте на Mail.Ru, уж извините, хотя за статью спасибо.
Я рад, что наша статья вызывает у вас положительные эмоции. Сейчас обхохочетесь еще больше:

Newmail.ru IMAP с 2001 г.
Hotbox.ru IMAP с 2002 г.
Gmail IMAP с 2008 г.

Обе почте несколько лет назад объединились в составе mail.qip.ru и здравствуют и поныне.
Вы Hotbox.ru и Newmail.ru ставите в один ряд с Gmail, Яндекс, Mail.Ru, тогда давайте начнем с 86?
Обе эти почты — это сейчас mail.qip.ru, которая по российской дневной аудитории где-то на уровне Rambler-почты, т.е. четвертая почта после Mail.Ru, Yandex и GMail. mail.qip.ru, конечно, по российской суточной аудитории отличается в разы от ближайшего к ней GMail, но и GMail в разы меньше Mail.Ru по тому же параметру.
ключевое слово «сейчас». И какое в данном контексте имеет значение российская аудитория или нет?
Как раз в те годы, когда там внедряли имап, эти сервисы были достаточно популярны, не только сейчас. Навскидку: у меня именно в 2001-м основной ящик был на newmail.ru, как и у многих моих друзей.

Актуальность имапа тогда была достаточно высока: веб-интерфейсы были убогие по современным меркам, почтовые программы были бесспорно удобнее. Интернет был дорогой и слабый, возможность не качать весь свой ящик, работать с папками на сервере выглядела достаточно привлекательно. Поддержка имапа этими сервисами в своем роде даже большее достижение, чем имап на гмейле в 2008-м.

Но если говорить именно про «сейчас», так в современном своем виде имап более актуален для мобильных клиентов, которые в силу своих ограничений по объему persistent-хранилища просто не могут адекватно работать с pop3. Если посмотреть на графики, то мобильных клиентов больше половины.

Но нормальная поддержка имапа, более-менее соответствующая RFC и работающая не только с gmail-ом и еще парой серверов, например, в андроиде появилась чуть позже появления версии 2.2, а это был уже 2010 год. В 2008-м не было такого рынка устройств, корректно поддерживающих imap, соответственно актуальность самого протокола была не так высока.

С 2008 года поменялось многое: команда почты mail.ru поменялась практически целиком, как поменялись и приоритеты. К сожалению, я не мог написать имап в 2008 году, как бы ни хотел, т.к. я еще тогда не работал в команде почты и в mail.ru вообще, а Денис тогда как раз делал поддержку имапа в яндексе :)

В своем посте я систематизировал технические нюансы реализации imap-а. Возможно, кому-то это будет просто любопытно, кому-то подкинет мыслей, скажем, при написании imap-клиента. Если бы я что-то в этом роде прочитал перед написанием сервера — мне это бы сэкономило некоторое количество времени. Если вам это неинтересно и вызывает лишь скептицизм — простите меня за то, что вы решили прочесть эту статью.
Как справедливо заметил Витя эти почты тогда занимали существенную долю рынка. Т.е. сейчас — это не ключевое слово. Российская аудитория имеет то значение, что вы упомянули gmail, у которого суточная аудитория world wide выше mail.ru в 4 раза. Если вы считаете их нашими конкурентами, то неявно подразумеваете, что речь только о России и возможно бывших советских республиках.
В Mail.Ru первый раз IMAP был запущен в 2005 году. И вполне успешно работал с популярными почтовыми клиентами того времени. Но популярность среди пользователей протокол не обрел, да и те кто им пользовался не охотно репортили баги, поэтому из-за отсутствия обратной связи с пользователями, и развитие поддержки имапа на стороне клиента ушло дальше возможностей имапа Mail.Ru. Повторный интерес к IMAP на мой взгляд — появился одновременно с ажиотажем на устройства с iOS и android. Появился интерес вот вам и обновленный IMAP 2012 Mail.Ru :)
Спасибо за статью! А можно вкратце про dovecot — помимо сложностей с прикручиванием к хранилищу, какие ещё с ним были проблемы? От него пришлось отказаться в основном из-за хранилища, или это была только половина проблемы?
В основном из-за хранилища. Но dovecot еще и очень прожорлив по процессору
мне кажется, что IMAP-сервер это как раз то, что надо садиться и писать на эрланге без всяких там глупостей с С =)

Логики много, она вся с таймаутами и запутанная.
Если говорить про написание просто абстрактно хорошего имап сервера, оно, наверное, так и есть: проще взять очень высокоуровневый, возможно функциональный, язык программирования, написать на нем лаконичный, красивый и аккуратный код без хаков.

Но у нас сервер, к сожалению, писался не совсем абстрактно: есть уже хранилище с достаточно громоздким C-шным API, кроме того, внутри проекта почты сервер-сайд сейчас пишут на С/C++, perl-е и python-е. Программистов на эрланге у нас в команде просто нет. Т.е. даже если сервер на нем и написать, то читать его код будет потом некому. Плюс, надо изобретать какие-то обертки для C-шного кода в эрланг, либо поддерживать 2 версии клиентской библиотеки к стороджу.

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

Да и на самом деле, на C++ при правильном подходе, код оказался довольно лаконичным: со всеми хаками для всех клиентов, там имапной специфики около 5000 строк. :)
Плюс, надо изобретать какие-то обертки для C-шного кода в эрланг

Для таких вещей все и придумывалось. Наш стримящий сервер был написан тоже в лохматые времена на C. Не мешает его испрльзовать через erlang. Тем более, не надо ничего изобретать!
www.erlang.org/doc/tutorial/c_port.html
Реальный пример использования:
github.com/zavr/erlxslt (многопоточная обертка над libxslt)

Программистов на эрланге у нас в команде просто нет.

Вопрос двух недель. У нас тоже не было.

Если Вы любите, TeX, пример — есть такие хорошие понятия в TeX как «блоки» и «клей». В переложении на мир технологий, erlang — и есть этот «клей». Это не просто еще один язык разработки, в том-то и его преимущество (мы же Вам не ocaml или haskell предлагаем).
Можно писать, на самом erlang все, но если уже что-то есть сделанное, не обязательно переписывать. Составные части, как мне кажется, логично продолжить писать на сях, а вот склеивать их эрлангом. Но это мое скромное мнение.
Вам, в вашей ситуации виднее.
Ну, т.е. с_port подразумевает еще один процесс-проксю? Не думаю, что наших админов бы это обрадовало :)

А на самом деле, я думаю, что описанный вами способ написания сервера — просто другой подход, который вполне хорош и имеет право на жизнь. Он имеет, как плюсы, так и минусы.

Вообще же, как показала практика, написать код сервера — это не так уж и сложно, независимо от языка. Повторюсь, но специфики имап там всего лишь 5к строчек. Правильно подружить все это дело с нашей инфраструктурой, с множеством разных клиентов — это было куда более сложной задачей, а тут уже язык не важен, важен подход.
c_port как вариант, а так, как настроите-сделаете. Обычно, да — но, это вроде как логично, но все настраиваемо. Может и erl_driver замутить.

Я во общем вас не агитирую, просто ответил, на не очень правильные аргументы с вашей стороны. А у программы все один критерий правильности: работает — значит не все плохо.

Ближе к теме:
5k хорошо комментированного, понятного кода, или как голые функции, c короткими именами и однобуквенные переменные?
Насчет качества кода — тут уж не мне судить, извините. Мне он, естественно, большей частью нравится :) Там в основном именно работа с протоколом, парс-форматирование, код достаточно простой и без rocket-science-а. C++ — довольно лаконичный язык, но, к сожалению, только если уметь его готовить.
Как это нет? Вот у вас есть люди, которые пишут сервер-сайд на С++? Они уже готовы писать на эрланге, пока компилится С-шный код.

Хм, ну уж нет. Я, например, лично не готов :) Толстовато, в общем)

Вообще, это странная тема… я могу более-менее читаемо, быстро и лаконично писать на C++(надеюсь, что так). Вы — на erlang. Если мы поменяемся местами, то, скорее всего, наша продуктивность резко снизится (во всяком случае, моя уж точно). Хуже от этого будет только пользователям mail.ru, которые получат имап позже :) При этом, при всех прелестях erlang-а, вряд ли я сразу напишу maintainable код.

А кроме erlang-а еще много интересных технологий. Говорят, в последнем .NET-е интересные фишки в плане асинхронности добавили, а еще он тоже быстро компилируется. Scala тоже интересный и красивый язык с функциональными плюшками.

Но если все пробовать, то кто и когда код писать-то будет? Да и по мне, так добавление еще одного языка, даже самого передового, в любой корпоративный зоопарк технологий только усложняет интеграцию.
А как же синергетический эффект? )

в плане асинхронности добавили

К сожалению, особенности .NET и java-машины, не позволяют, на мой взгляд, сделать полноценную асинхронность. Во общем, есть на то математические основания.

получат имап позже

Возможно, а возможно и раньше. + есть одна важная деталь — сопровождение. Не только сегодняшним днем живем. И не в любых своих (и чужих) исходниках двухлетней давности приятно разбираться.

Как раз для изучения плюсов и минусов той или иной технологии, применительно к текущим задачам и нужны в компании консультанты.
В плане .NET — я на нем писал давно и не очень много. Но об этих улучшениях написано в release notes, друзья говорили, что стало удобнее. Это был просто пример того, что есть и другие интересные технологии, которые в принципе можно попробовать :)

Получат позже — потому что непосредственно написание кода заняло реально малый процент времени. Я знаю, что на новом для себя языке я бы писал не так быстро и код был бы хуже, как минимум, первые полгода. На нормальное овладение технологией, имхо, уходит не один месяц и не один проект.

Я лично, как инженер, считаю, что язык программирования — не главное. На практически любом языке можно сделать удобную для проекта и задач платформу. Главное — хорошо владеть выбранным инструментом.

Консультанты — это хорошо, но я помню, что в Parallels, например, по совету консультантов начали пытаться переписывать всю автоматизацию на java. Имхо, это был очень странный шаг, который стоил компании нескольких толковых специалистов и отнял порядочно времени. С любым подходом главное — не перестараться :)
Это ветка, конечно, похожа на холивар, но Вы приводите интересные и очень разумные аргументы, потому предлагаю продолжить.
Получат позже
Я с Вами согласен, что применять что-то пилотное в активном и критически важном проекте — не правильно. Но, как мне кажется, нужно смотреть дальше чем один проект. Живем не сегодняшним днем, и Ваши 5k строк через некоторое время могут превратиться в 50k, 500k строк (и это нормально) и их надо будет как-то поддерживать. Если есть немного свободного времени, посмотрите Cesarini F. Erlang programming, и сравните с тем что уже имеете.
язык программирования
Согласен, но как лингвист, я скажу что любые языки принципиально не эквивалентны. Сам язык, что — просто набор правил над некоторым множеством символов. Но за каждым естественным языком стоит его культура. За искусственным — парадигма, или архитектура абстрактной машины этого языка.
Знание внешней оболочки языка, без понимания основания делает человека «языковым чудищем». Вы просто спросили как пройти, а вам морду набили.
Парадигмы-то они эквивалентны, но некоторые вещи в лямда выражениях выглядят проще, удобнее, эффективнее, чем в рамках стековой машины (java, .net, python) или машины фон Неймана (C\C++, Fortran).
сделать удобную для проекта и задач платформу
По сути, тоже реализация некоторого языка, на основе существующего. А такое лучше делать на функционального подхода. + Делать платформу — это тоже время. А если она станет одноразовой, и даже частично не применимой, к чему-то другому — слишком дорого.
Локальные решения это хорошо, но только они не позволяют находить других локальных решений, которые, может быть, лучше. Траншею можно копать саперной лопаткой, а можно экскаватором. Если траншея одна в принципе, то лопатой, конечно быстрее. Она получится даже аккуратнее. А на экскаваторщика придется еще учиться. Но если траншей сотни, то лопата уже не применима.
пока компилится С-шный код.

Вот тут мне кажется, ты не прав. Что такое у тебя долго компилировалось? И как долго?
Имхо, такие 5k как раз, скомпилятся вполне себе быстро.
это какие 5К строк. Если с бустом и локи, то поспать успеешь. Если попроще код, то шустро разгребется.
Посмотрел на dovecot — там вроде бы вполне прозрачная система плагинов для хранилищ. Неужели настолько плохо совместимыми оказались его API и API хранилища — настолько, что написать с нуля сервер оказалось дешевле? Или, как ответили выше, процессорное время тоже стало узким местом (или ещё что-то)?
В общем случае, dovecote надо допиливать напильником, если у вашего хранилища ни один из поддерживаемых им форматов. Вот тут подробности: wiki2.dovecot.org/MailboxFormat
Ну и процессорное время тоже жалко. В свое время, когда я работал техдиром в Почте.ру, у нас была IMAP-прокси в лице dovecote. Переделав ее на свою собственную, мы уменьшили количество серверов для IMAP-прокси в 10 раз.
Там основная проблема в том, что у нас другие требования к индексам. Как пример: imap-сервер может позволить себе сохранить в индексе уже готовый ответ на fetch bodystructure, для нас это было бы слишком дорого как в смысле избыточности, так и в смысле переиндексации. У нас структура письма в индексах хранится в виде дерева, и используется imap-ом, веб-интерфейсом, и даже pop3.

Кроме того, письма у нас хранятся не по RFC, а в другом, чуть более компактном виде.

Фактически нам надо было бы научиться формировать на лету ответы bodystructure/envelope из данных в нашем формате, прикрутить какие-нибудь хаки для того, чтобы без лишних оверхедов на I/O отдавать части письма, попутно преобразуя их к RFC-виду. Потом надо было бы прикрутить общение с нашей базой юзеров.

На самом деле, примерно этим и занимается 80-90%% кода нашего имап-сервера.Т.е. какую часть dovecot-а мы реально смогли бы переиспользовать? По сути, только работу с сокетами и парсинг протокола. И то, ее, скорее всего пришлось бы патчить, чтобы не есть лишнего CPU.

Кроме того, dovecot — сторонний для нас проект, он живет своей жизнью и любые плагины и правки нам надо будет мерджить с новыми изменениями самого сервера, либо взять на себя поддержку проекта из 300 тыс строк.

В результате плюсы от написания своего сервера перевесили минусы.

блин, но у вас бы хоть IDLE был. ладно NOTIFY (редкая вещь), но хоть IDLE… и QRESYNC… а щас в итоге ни фига нет до сих пор) вы кстати там ещё работаете? есть какие-нибудь планы по развитию IMAP сервера?
Рапортую: IMAP работает просто великолепно. Подключил с первого раза без проблем. Огромное спасибо!
Почему-то сейчас не могу установить для ящика возможность использовать IMAP, как на iOS 6 так и в Mail.App OS X 10.8.2. Всё время видится только POP3
У Apple что то сломалось. Мы сейчас в активной переписке с ними. Просим вернуть автонастройку imap.
Спасибо за быстрый ответ :)
Пока рекомендуем воспользоваться следующим хаком. Вводите при настройке неверный пароль, и вам предложат выбрать поп или имап с ручной настройкой параметров сервера.
Сработало! :) Спасибо!
Спасибо за статью. Хоть я и не программист, но было очень интересно почитать.
Кто что может посоветовать (из почтовых серверов) для компании (200 пользователей). Средний размер ящика 10 ГБайт (максимум — 30 ГБайт). Средне кол-во писем в ящике — 30000.
Сейчас используем dovecot. Клиенты — Thunderbird. У всех IMAP без кеширования почты на диск.
Спасибо!
Зарегистрируйтесь на Хабре, чтобы оставить комментарий