IMAP и POP Gmail через telnet или читать почту это просто

    Я решил написать эту статью после того, как мне потребовалось написать простенький почтовик, который будет обслуживать почту из Gmail. Надеюсь, что кому-то стало проще жить — хоть в целом это выглядит как пособие от Капитана Очевидность :) Всю необходимую для написания клиента информацию я нашёл в гугле минут за 10 — но считаю, что простенький мануал типа такого — хорошая шпаргалка на будущее :)

    В этом нет ничего сложного — правда! Фактически — написать свой почтовик — проще простого. Так же просто как и читать почту через консоль.

    Далее — две маленькие статьи на живых примерах — как пользоваться POP3 и IMAP без почтового клиента.


    Читаем POP3



    Вам потребуется Linux. Ну или поддержка OpenSSL в Windows — если она у вас есть — то, вероятно, статья не для вас — вы и так всё знаете :)

    Далее — набор команд с расшифровкой:

    openssl s_client -crlf -ign_eof -connect pop.gmail.com:995

    Мы коннектимся на гмейл с использованием SSL. Параметр -crlf гарантирует что нам не придётся испытывать проблем с переносом строк и наши команды будут распознаны так, как надо.
    Параметр -ign_eof обещает нам, что команды, начинающиеся с буквы R будут корректно восприняты s_client и не вызовут разрыва SSL.

    В случае успешного соединения мы видим что-то типа следующего:
    CONNECTED(00000003)
    ...куча букв и цифр, свидетельствующих о SSL
    +OK Gpop ready for requests from 79.165.189.32 3pf3718132bwz.16


    Это значит что на первом этапе всё прошло отлично и мы присоединились к почтовику Гугла.
    Далее нам следует авторизоваться.

    USER логин БЕЗ gmail.com

    В случае успешного прохождения команды мы видим строчку:

    +OK send PASS

    Нас просят ввести пароль. Что мы и сделаем:

    PASS ваш_пароль


    В случае если пароль верен — нас пускают внутрь!
    +OK Welcome.


    Вот мы и внутри нашего почтового ящика.
    Давайте проверим — пришли ли нам новые сообщения?

    STAT


    Я увидел следующее:

    +OK 15 1408449


    Это значит, что на сервере у меня 15 непрочитанных писем общим размером 1 408 449 байт.

    Интересно — а сколько весит каждое непрочитанное письмо?

    LIST


    Вот и список сообщений:

    +OK 15 messages (1408449 bytes)
    1 3423
    2 42610
    3 3693
    4 3693
    5 445122
    6 1933
    7 3488
    8 3760
    9 3155
    10 439325
    11 9071
    12 3125
    13 3575
    14 3997
    15 438479


    Видите — пока ничего сложного :)

    Давайте прочитаем пятое сообщение — что-то в нём много байт — наверное, интересное письмо!

    Для чтения письма доступна команда TOP
    TOP 5 0


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


    From: root <bender@skazkin.ru>
    To: master@skazkin.ru
    Subject: Cron <root@skazkinserver> perl /home/common/parser.pl queue



    Мне пришёл отчёт с моего сервера — что парсер закончил строить очередь. Хорошо, читать мне это не очень интересно — там разная служебная информация.
    Пометим его для удаления

    DELE 5


    Гмейл понял нас —

    +OK marked for deletion


    Гмейл удалит отмеченные для удаления письма после выхода из системы.

    Прочитаем самое маленькое письмо —

    TOP 6 0


    Subject: =?KOI8-R?B?0NLJ18XU?=
    From: =?KOI8-R?B?4c7Uz84g58HCz9c=?= <друг gmail.com>
    To: Andrew Skazkin <мне gmail.com>
    Content-Type: text/plain; charset=ISO-8859-1


    Ого — не читается :(
    Это уже решается почтовыми клиентами — тема письма — в кодировке KOI8-R и зашифрована BASE64.

    Чтож, почта прочитана и пора выходить.

    Я так подумал — не буду я удалять письмо от Cron.

    RSET

    Эта команда сбрасывает флажки на удаление у писем, которые мы отметили для удаления.

    +OK


    Такой ответ — в случае успеха. Теперь можно выйти.

    QUIT


    Ответом нам —

    +OK Farewell.
    read:errno=0


    Вот и всё. С POP3 мы разобрались, не так ли? Пришла пора для IMAP.

    Играемся с IMAP



    Процедура мало чем отличается — только лишь командами.

    openssl s_client -crlf -ign_eof -connect imap.gmail.com:993


    Опять выдала нам кучу букв и цифр, и последняя строчка —

    +OK Gpop ready for requests from 79.165.189.32 1pf4035116fxm.33


    Входим в аккаунт:

    . login я gmail.com мойпароль


    Успешно!

    * CAPABILITY IMAP4rev1 UNSELECT LITERAL+ IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE
    . OK я gmail.com authenticated (Success)


    Обратите внимание — все команды предваряются точкой и пробелом!

    Получим список наших папок в аккаунте:

    . list "" "*"


    Нам вываливается список папок:

    * LIST (\HasNoChildren) "/" «Cron»
    * LIST (\HasNoChildren) "/" «INBOX»
    * LIST (\HasNoChildren) "/" «LJ»
    * LIST (\HasNoChildren) "/" «Proxies»
    * LIST (\HasNoChildren) "/" «WordPress»
    * LIST (\Noselect \HasChildren) "/" "[Gmail]"
    * LIST (\HasNoChildren) "/" "[Gmail]/&BBIEQQRP- &BD8EPgRHBEIEMA-"
    * LIST (\HasNoChildren) "/" "[Gmail]/&BBoEPgRABDcEOAQ9BDA-"
    * LIST (\HasNoChildren) "/" "[Gmail]/&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-"
    * LIST (\HasNoChildren) "/" "[Gmail]/&BB8EPgQ8BDUERwQ1BD0EPQRLBDU-"
    * LIST (\HasNoChildren) "/" "[Gmail]/&BCEEPwQwBDw-"
    * LIST (\HasNoChildren) "/" "[Gmail]/&BCcENQRABD0EPgQyBDgEOgQ4-"
    . OK Success


    То, что с непонятными символами — папки, названные по-русски.

    Сколько у нас писем в папке INBOX?

    . status INBOX (messages)


    Ответ —
    * STATUS «INBOX» (MESSAGES 8)
    . OK Success


    Ого! Есть новая почта! Почитаем её:

    . select inbox


    Выборка успешна:
    * FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
    * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)]
    * OK [UIDVALIDITY 2]
    * 8 EXISTS
    * 0 RECENT
    * OK [UIDNEXT 68967]
    . OK [READ-WRITE] inbox selected. (Success)


    Посмотрим — что из восьми писем ещё не прочитано:

    . fetch 1:* flags


    Эта команда выбирает флаги для всех писем, начиная с первого.

    * 1 FETCH (FLAGS (\Seen))
    * 2 FETCH (FLAGS (\Seen))
    * 3 FETCH (FLAGS (\Seen))
    * 4 FETCH (FLAGS (\Seen))
    * 5 FETCH (FLAGS (\Seen))
    * 6 FETCH (FLAGS ())
    * 7 FETCH (FLAGS ())
    * 8 FETCH (FLAGS ())
    . OK Success


    Прочитаем седьмое письмо — его заголовки

    . fetch 7 full


    * 7 FETCH (ENVELOPE («Fri, 20 Nov 2009 09:58:35 +0000» "=?KOI8-R?B?79TXxdTJ1NggzsEg08/Pwt3FzsnFICfSwcLP1MXOy8EgzsEgMSDCwcvTJw==?=" (("=?KOI8-R?B?5s/S1c0gzyDQz8nTy8/X2cgg08nT1MXNwcg=?=" NIL «root» «searchengines.ru»)) (("=?KOI8-R?B?5s/S1c0gzyDQz8nTy8/X2cgg08nT1MXNwcg=?=" NIL «root» «searchengines.ru»)) (("=?KOI8-R?B?5s/S1c0gzyDQz8nTy8/X2cgg08nT1MXNwcg=?=" NIL «root» «searchengines.ru»)) ((NIL NIL «master» «skazkin.ru»)) NIL NIL NIL "<200911200935.b8f41f512510@forum.searchengines.ru>") FLAGS () INTERNALDATE «20-Nov-2009 09:58:38 +0000» RFC822.SIZE 4045)
    . OK Success


    В целом конечно понятно — но хотелось бы ещё понятнее

    . fetch 7 (body[header.fields (from to subject date)])


    Выбираем только интересные заголовки:

    * 7 FETCH (BODY[HEADER.FIELDS (from to subject date)] {334}
    Date: Fri, 20 Nov 2009 09:58:35 +0000
    To: master@skazkin.ru
    From: =?windows-1251?q?=D4=EE=F0=F3=EC_=EE_=EF=EE=E8=F1=EA=EE=E2=FB=F5_=F1=E8=F1=F2=E5=EC=E0=F5?=
    <root@searchengines.ru>
    Subject: =?windows-1251?q?=CE=F2=E2=E5=F2=E8=F2=FC_=ED=E0_=F1=EE=EE=E1=F9=E5=ED=E8=E5_=27=F0=E0=E1=EE=F2=E5=ED=EA=E0_=ED=E0_1_=E1=E0=EA=F1=27?=


    Прочитаем тело письма:

    . fetch 7 rfc822.text

    Вот и оно:

    * 7 FETCH (RFC822.TEXT {1299}
    … сообщение в кодировке windows-1251
    . OK Success


    В целом, как видите, нет ничего сложного чтобы управляться с консольными выводами POP3 и IMAP.

    Разница только в том, что IMAP — понавороченнее, а POP3 обладает весьма урезанным функционалом — и позволяет читать только почту, которая лежит в папке INBOX.

    Вспомогательная информация:
    Хороший мануал по IMAP
    IMAP RFC
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      +3
      Для жесточайших гиков :-)
      Пальцы загнуть можно конкретно :-) «Дай-ка телнета почту проверить» :-D
        0
        Я долго пользовался таким методом, но оказалось, что по POP3 команда LIST имеет ограничение в неcколько сотен писем :-( Когда инбокс перевалил за 300-400 писем, пришлось осваивать IMAP.

        Спасибо за топик. Узнал кое-что новенькое.
          0
          А что за ограничение? По идее STAT должен показывать общее количество писем — и в скрипте потом это можно хендлить порционным фетчем :)
            0
            Я так глубоко не разбирался :-) Столкнулся с тем, что LIST выдаёт только 300-400 писем. Причём старых. Новые не видны. Меня это огорчило и я перешёл на IMAP.
            Я чувствую, — вас есть решение? Спасибо!
              0
              О, попробовали сейчас — выдал максимум 700 из 14 000. Притом даты писем странные — чередуются старые, новые — в общем разброс очень большой. В RFC не написано про это. Видимо, моральная устарелость протокола имеет место быть :)

              Алгоритм в целом правда ясен — получается что есть, потом список обновляется — но не в рамках одной сессии — и так до конца.
                0
                Возможно сказывается ограничение программы, которой подключаетесь. Она ждет пока не вычитает данные с сокета — потом обрывается если не увидела очередной порции данных в сокете. Почтовые клиенты, например, могут ожидать последовательность символов, указывающих на завершение комманды.
                Можете повесить сниффер wireshark на POP порт и вытянуть почту вашим почтовым клиентом. Посмотрите что вернет LIST.
                  0
                  Фишка в том, что LIST через телнет отдаёт N писем и потом говорит — +ОК, — типа всё что есть — получите-распишитесь.

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

                  Если, например, сделать RETR — это письмо (не тестили глубоко, только по последнему ID) не появится в списке — ну и так пока письма не кончатся. То есть клиент потенциально делает проверочный LIST после полученной пачки писем.
          • НЛО прилетело и опубликовало эту надпись здесь
              0
              А я вообще всегда использую прямое общение с портом (nc/telnet) для проверки работоспособности почтового сервера — позволяет исключить проблемы клиентской части.

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое