Google, куда ты дел моё место в GMail? А вы точно знаете, как в GMail работают метки?

от автора


Стал я замечать, что из 15 гигабайт бесплатного месте, предоставленного Google, у меня почта занимает уже почти 12 гигабайт. И такая тенденция меня не радует.
С другой стороны я в качестве почтового клиента использую Thunderbird с полной синхронизацией. Т.е. все письма должны быть закачены. Так вот папка Thunderbird со всеми письмами и индексами занимает всего 3 гигабайта. Хотя по логике вещей размер должен не просто более менее совпадать с занятым местом на GMail, а быть побольше, т.к. Thunderbird не архивирует письма, а хранит как есть и еще индексы строит для ускорения поиска.
Проблема на лицо! Начинаем докапываться до сути.

Начал я того, что зашёл в ярлык (да, в случае с GMail правильно говорить именно ярлык, а не папка, подробности тут) «Вся почта» и увидел, что у меня чуть больше 500 тысяч сообщений. Ситуация усложнялась тем, что у меня порядка 100 ярлыков! А ярлыки в GMail — это типичные папки в Thunderbird. Как быстро посчитать общее количество писем в Thunderbird я не нашел. Но забегая вперед скажу, что в нем у меня их порядка 200 тысяч. Отсюда становится понятно, почему на диске место занимается меньше.
Но остается все равно все тот же вопрос: что это за такие 300 тысяч сообщений в GMail, которые не видны в Thunderbird, но занимают место на GMail?

Пытливость ума + желание не поспать ночью + желание пощупать Go на реальной задаче привели меня к решению, что нужно взять компилятор Go, изучить GMail API и посмотреть, что же там под капотом у GMail.

Совсем коротко о впечатлениях о Go

Только самый ленивый не писал про обработку ошибок в Go. Только на них я и обратил внимание более пристально.
В остальном:

  • Начал писать на следующий вечер
  • Еще один язык
  • Жизнь заставит — буду писать и на Go
  • Для меня и C/C++, Python, Java (и PHP тоже) — тоже себе языки для своих ниш
  • Наверное я просто всеядный

Да и статья не про Go.

Как я выше отметил, у меня порядка сотни ярлыков. Письма обычно имеют один ярлык. И мне захотелось выяснить, сколько писем у меня помечены каждым ярлыком и сколько они суммарно занимают места.
Я не нашел способа узнать в web-интерфейсе GMail размеры ярлыков (объём писем, помеченных тем или иным ярлыком).
Засучил рукава, установил компилятор Go, поднял в Docker контейнере MongoDB (Да, я такой вот извращенец! Но это мой pet project и что хочу, то и использую, особенно в учебных целях) и стал говнокодить творить.
Дальше я буду ссылаться на вот этот мой проект.
Забираю все свои метки с GMail и складываю их в базу Users.labels: list:

GMailMessagesSize -importLabels -mongoConnectionString 10.211.55.5 Imported labels: 112 

Забираю ID всех сообщений, которые имеются в ящике Users.messages: list:

GMailMessagesSize -mongoConnectionString 10.211.55.5 -importMessages Processed 100 messages Processed 200 messages Processed 300 messages ....... Processed 523100 messages Processed 523115 messages 

Забирается конечно не быстро, но как тут распараллелиться я не нашел (API не позволяет).
Пока у нас есть только список ID сообщений, а нам нужно про каждое сообщение знать его ярлыки и размер. Для этого есть метод Users.messages: get. Но отрабатывает он не быстро, даже не смотря на то, что в запросе я указываю какие именно поля меня интересуют (internalDate, labelIds, sizeEstimate).
Реализацию Batching Requests я что-то не нашел.
Но я же пишу на Go и грех не использовать горутины! Сказано — сделано. Тянем информацию в количество потоков (сколько захотим, но я поставил ограничение в 50). Если интернет быстрый и комп не тупит, то начинаем быстро упираться в лимит рейта запросов от Google. Скрипт можно остановить и продолжить, а можно просто упорно ждать, т.к. при срабатывании лимита горутины спят по 5 секунд и потом продолжают мучить Google. Да, можно было бы каждый раз увеличивать время сна, например, в два раза и не забыть про ограничение сверху. Но в этом случае простые 5 секунд вполне себе решение.
Я свои 500 тысяч писем обработал суммарно, кажется, примерно за 3 часа. В общем время вменяемое.

GMailMessagesSize -mongoConnectionString 10.211.55.5 -processMessages -procNum 20 ............................Procecced 100 messages ............................Procecced 200 messages ............................Procecced 300 messages .... ............................Processed 523100 messages ............................Processed 523115 messages 

Там не только точки выскакивали. Если упереться в лимит, то вместо точки S (sleep) или может быть сообщение уже было удалено, то NF (NotFound).
В результате всех перечисленных выше страданий в MongoDB имеется коллекция ярлыков и коллекция сообщений:

{      "SizeEstimate" : NumberLong(63422),      "_id" : ObjectId("5677188d2afd90a80e5e06f2"),      "id" : "136b83b1ff739dec",      "internaldate" : ISODate("2012-04-15T22:47:51.000+0000"),      "labelids" : [         "CATEGORY_PROMOTIONS"     ],      "processed" : true } 

Теперь под рукой есть все данные, чтобы начать их анализировать.
Сначала я решил экспортировать в CSV информацию по ярлыкам, количеству сообщений и их суммарный размер.

GMailMessagesSize -mongoConnectionString 10.211.55.5 -showSizes LabelId;Label name;Messages size;Messages count Label_11;Archives;21279;4 Label_12;Archives/2012;18684;3 CATEGORY_FORUMS;CATEGORY_FORUMS;519396295;30038 CATEGORY_PERSONAL;CATEGORY_PERSONAL;5040188875;268116 CATEGORY_PROMOTIONS;CATEGORY_PROMOTIONS;2990655727;36508 CATEGORY_SOCIAL;CATEGORY_SOCIAL;205976374;6553 CATEGORY_UPDATES;CATEGORY_UPDATES;2769764066;180729 CHAT;CHAT;0;0 DRAFT;DRAFT;82817;6 IMPORTANT;IMPORTANT;6600492209;159268 INBOX;INBOX;40306538;334 UNREAD;UNREAD;479586429;11678 ..... Label_97;INBOX/Coursera;6021524;151 Label_77;INBOX/Временная;1077571;28 Label_63;INBOX/Ответить!!!;6195999;12 Label_67;INBOX/Поездка в США;1693366;11 

Это CSV, который мне было удобно открыть в Excel и поизучать (посортировать и фильтровать).

И вот на этом этапе я серьезно задумался. Что такое 6 гигов каких-то важных ( с ярлыком IMPORTANT ) сообщений? Что такое 11678 непрочитанных сообщений (с ярлыком UNREAD)? У меня (как я думал) все сообщения прочитаны! Даже если в строке поиска GMail ввести label:unread, то он выводит всего 106 непрочитанных сообщений! Что происходит?

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

На этом месте те, кто пользуется GMail’ом исключительно в браузере могут пожалеть, что начали читать эту статью. НО!!! Вы возможно читаете почту в том числе с мобильного. И возможно у вас там не родной клиент GMail. В таком случае, возможно у вас такая же проблема, как и у меня!

Не буду дальше томить и расскажу, что же все таки происходит.
Следите за руками. Последовательность событий такая:

  1. Приходит письмо в GMail
  2. Письму назначается ярлыки INBOX, UNREAD и (вот тут важно) возможно еще какой-нибудь дополнительный ярлык, например CATEGORY_PROMOTIONS
  3. В почтовом клиенте вы открыли письмо. Ярлык UNREAD снялся.
  4. В почтовом клиенте вы удалили письмо
  5. Барабанная дробь: ярлык INBOX снялся. И… все, больше ничего
  6. У сообщения остался ярлык CATEGORY_PROMOTIONS

Сообщения с ярлыком CATEGORY_PROMOTIONS отображаются, если в поиске набрать: category:promotions Часто вы так делаете?
Если уж совсем коротко, то письма просто не удаляются! Я их удаляю, а они остаются на GMail.
Тут самое время вспомнить про архивацию писем. И похоже, что это тот самый случай!
Когда в Thunderbird удаление настроено через «Пометить на удаление», потом «Сжатие»:

И то, что стоит галка помещать в корзину:

То происходит ВСЕ РАВНО архивация!
Итого: письма уходят в архив. А архив с точки зрения GMail — это письма, которые не имеют видимых ярлыков и не побывали в корзине.
С одной стороны — ничего страшного. Зато письма всегда можно будет найти через поиск.
А что если я не хочу так? Что мне теперь делать?
Как найти и удалить все сообщения из архива? Вот тут неплохой ответ. Но я что-то не рискнул вот так вот удалять все и сразу.
Кстати, в строке поиска я так и не нашел способа показать сообщения, которые имеют только один конкретный ярлык. Т.е. например, я решил удалить все сообщения, которые имеют ярлык CATEGORY_PROMOTIONS и никакой другой. Эти рекламные письма в архиве мне точно не нужны. Кстати, а сколько их там?

GMailMessagesSize -mongoConnectionString 10.211.55.5 -showSizes -l CATEGORY_PROMOTIONS -onlyThisLabel LabelId;Label name;Messages size;Messages count CATEGORY_PROMOTIONS;CATEGORY_PROMOTIONS;1197364170;14618 

У меня их там на гигабайт накопилось.
-onlyThisLabel важная опция, которая как раз и позволяет найти только те сообщения, которые имеют этот единственный ярлык.

GMailMessagesSize -mongoConnectionString 10.211.55.5 -showSizes -l CATEGORY_PROMOTIONS -l IMPORTANT -onlyThisLabel LabelId;Label name;Messages size;Messages count CATEGORY_PROMOTIONS;CATEGORY_PROMOTIONS;1197364170;14618 

Да у меня еще на полтора гигабайта «важных рекламных» сообщений 🙂 Обратите внимание, что это в дополнение к просто гигабайту неважной рекламы.
Руки сразу зачесались все это удалить!

GMailMessagesSize -mongoConnectionString 10.211.55.5 -deleteMessages -l CATEGORY_PROMOTIONS -l IMPORTANT -onlyThisLabel -procNum 10 

На самом деле письма не удаляются, а помещаются в корзину. Там они через 30 дней либо удалятся совсем, либо можно пойти и вручную почистить самому.

ИТОГО: Если вы удаляете сообщения не через Web-интерфейс GMail, а через сторонний клиент (возможно мобильный), то есть вероятность, что сообщения у вас не удаляются, а архивируются. Для некоторых это даже хорошо. А у кого-то это приводит к тому, что ящик просто неприлично распухает.
И дело даже на в 2 баксах в месяц. Можно и 100 гигов скушать и дальше больше. Хотелось именно разобраться в сути вопроса.

ВНИМАНИЕ!!! Проект писался лично для себя. Это моя первая программа на Go. За сохранность ваших писем я не отвечаю! Но если не пользоваться опцией -deleteMessages, то ничего с вашим ящиком не случится.

Что сделать, чтобы приложение заработало?

  • Use this wizard to create or select a project in the Google Developers Console and automatically turn on the API. Click Continue, then Go to credentials.
  • At the top of the page, select the OAuth consent screen tab. Select an Email address, enter a Product name if not already set, and click the Save button.
  • Select the Credentials tab, click the Add credentials button and select OAuth 2.0 client ID.
  • Select the application type Other, enter the name «Gmail API Quickstart», and click the Create button.
  • Click OK to dismiss the resulting dialog.
  • Click the (Download JSON) button to the right of the client ID.
  • Move this file to your working directory and rename it client_secret.json.

Подскажите, а для вас проблема с размером ящика GMail актуальна? Нужно ли довести мою поделку до ума, чтобы вы могли выборочно почистить свои архивные сообщения?

Никто ещё не голосовал. Воздержавшихся нет.

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

ссылка на оригинал статьи http://habrahabr.ru/post/273701/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *