![](https://habrastorage.org/files/2c3/c9a/c28/2c3c9ac28f1641879c76e924be443e61.png)
Стал я замечать, что из 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.
В остальном:
- Начал писать на следующий вечер
- Еще один язык
- Жизнь заставит — буду писать и на 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 и поизучать (посортировать и фильтровать).
![](https://habrastorage.org/files/736/ea7/c60/736ea7c6047e4fe5bd9ce0d3b0bf3aec.png)
И вот на этом этапе я серьезно задумался. Что такое 6 гигов каких-то важных ( с ярлыком IMPORTANT ) сообщений? Что такое 11678 непрочитанных сообщений (с ярлыком UNREAD)? У меня (как я думал) все сообщения прочитаны! Даже если в строке поиска GMail ввести label:unread, то он выводит всего 106 непрочитанных сообщений! Что происходит?
Гугление данной ситуации привело к форумам, где другие задавались вопросом — почему удаленные в Thunderbird сообщения не удаляются в GMail? Ну там много разных случаев. Я вам расскажу о самом, на мой взгляд, печальном.
На этом месте те, кто пользуется GMail'ом исключительно в браузере могут пожалеть, что начали читать эту статью. НО!!! Вы возможно читаете почту в том числе с мобильного. И возможно у вас там не родной клиент GMail. В таком случае, возможно у вас такая же проблема, как и у меня!
Не буду дальше томить и расскажу, что же все таки происходит.
Следите за руками. Последовательность событий такая:
- Приходит письмо в GMail
- Письму назначается ярлыки INBOX, UNREAD и (вот тут важно) возможно еще какой-нибудь дополнительный ярлык, например CATEGORY_PROMOTIONS
- В почтовом клиенте вы открыли письмо. Ярлык UNREAD снялся.
- В почтовом клиенте вы удалили письмо
- Барабанная дробь: ярлык INBOX снялся. И… все, больше ничего
- У сообщения остался ярлык CATEGORY_PROMOTIONS
Сообщения с ярлыком CATEGORY_PROMOTIONS отображаются, если в поиске набрать: category:promotions Часто вы так делаете?
Если уж совсем коротко, то письма просто не удаляются! Я их удаляю, а они остаются на GMail.
Тут самое время вспомнить про архивацию писем. И похоже, что это тот самый случай!
Когда в Thunderbird удаление настроено через «Пометить на удаление», потом «Сжатие»:
![](https://habrastorage.org/files/862/317/296/862317296cf545caa869d146882a6e61.png)
И то, что стоит галка помещать в корзину:
![](https://habrastorage.org/files/7d2/bd9/2e5/7d2bd92e5dbc402e90bf23bdaaa513d1.png)
То происходит ВСЕ РАВНО архивация!
Итого: письма уходят в архив. А архив с точки зрения 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 актуальна? Нужно ли довести мою поделку до ума, чтобы вы могли выборочно почистить свои архивные сообщения?
61.51% Мне бесплатных 15 гигабайт хватит на две жизни, т.к. мне приходит одно сообщение в день1125
3.23% Я купил 30 терабайт у Google и размер ящика GMail меня не беспокоит59
30.4% Я бы поразбирался с тем, что и как у меня хранится в ящике GMail и удобный инструмент мне был бы полезен556
4.87% У меня нет GMail аккаунта89
Проголосовали 1829 пользователей. Воздержались 447 пользователей.