- Gmail to SQLite, Gmail iletilerini yerel bir SQLite veritabanına senkronize ederek analiz ve arşivleme için kullanmayı sağlayan bir Python uygulamasıdır
- Varsayılan davranış yalnızca yeni iletileri indiren artımlı senkronizasyondur; tam senkronizasyon seçeneğiyle tüm iletiler indirilebilir ve silinme durumu da tespit edilebilir
- İleti alma işlemi çok iş parçacıklı paralel işleme kullanır; üstel geri çekilme tabanlı otomatik yeniden deneme ile CTRL+C işleme gibi hata ve sonlandırma önlemlerini içerir
- Çalıştırmak için Python 3.8 veya üzeri, Gmail API etkinleştirilmiş bir Google Cloud Project ve OAuth 2.0
credentials.json dosyası gerekir
- Kaydedilen veriler; gönderen, alıcılar, etiketler, gövde, boyut, okunma durumu, gönderilmiş olup olmadığı ve silinmiş olup olmadığı gibi alanları içerir; böylece Gmail kullanım kalıpları SQL ile doğrudan analiz edilebilir
Gmail iletilerini yerel olarak senkronize etme aracı
- Gmail to SQLite, Gmail iletilerini yerel bir SQLite veritabanına kaydeden bir Python uygulamasıdır
- Amacı, Gmail verilerini analiz ve arşivleme için kullanılabilir hâle getirmektir
- Kod tabanının genelinde type hint uygulanarak tip güvenliği sağlanmıştır
Senkronizasyon yöntemi ve kararlılık
- Varsayılan senkronizasyon, artımlı senkronizasyon olarak çalışır ve yalnızca yeni iletileri indirir
--full-sync seçeneği kullanıldığında tüm iletiler senkronize edilir ve Gmail'de silinen iletiler tespit edilir
- İleti alma işlemi performansı artırmak için çok iş parçacıklı paralel işleme ile gerçekleştirilir
- Hata işleme otomatik yeniden deneme ve üstel geri çekilme içerir
- CTRL+C'ye basıldığında düzgün bir kapanış süreci çalıştırılır
- Yeni iş kabul etmeyi durdurur
- Çalışmakta olan işlerin bitmesini bekler
- Tamamlanan işlerin ilerleme durumunu kaydeder
- Normal şekilde kapanır
- CTRL+C'ye bir kez daha basılırsa hemen sonlandırılır
Kurulum ve ön koşullar
- Çalışma ortamında Python 3.8 veya üzeri gerekir
- Gmail API etkinleştirilmiş bir Google Cloud Project gerekir
- OAuth 2.0 kimlik doğrulama dosyası
credentials.json, proje kök dizininde bulunmalıdır
- Kurulum akışı, depoyu klonladıktan sonra
uv sync ile bağımlılıkları yükleme şeklindedir
- Gmail API kimlik doğrulama ayarı için Google Cloud Console'da bir proje oluşturulur veya seçilir, Gmail API etkinleştirilir, ardından Desktop application için OAuth 2.0 kimlik bilgileri oluşturulup
credentials.json olarak kaydedilir
Komut kullanımı
- Temel artımlı senkronizasyon şu şekilde çalıştırılır
python main.py sync --data-dir ./data
# or: uv run main.py sync --data-dir ./data
- Tam senkronizasyon ve silme tespiti için
--full-sync kullanılır
python main.py sync --data-dir ./data --full-sync
- Yalnızca belirli bir iletiyi senkronize etmek için
sync-message ve --message-id kullanılır
python main.py sync-message --data-dir ./data --message-id MESSAGE_ID
- Yalnızca silinen iletileri tespit edip göstermek için
sync-deleted-messages kullanılır
python main.py sync-deleted-messages --data-dir ./data
- Worker iş parçacığı sayısı
--workers ile belirtilebilir; varsayılan değer CPU çekirdeği sayısıdır
python main.py sync --data-dir ./data --workers 8
- Komut satırı argümanları şöyledir
command: Zorunludur; sync, sync-message, sync-deleted-messages değerlerinden biri
--data-dir: Zorunludur; SQLite veritabanının kaydedileceği dizin
--full-sync: İsteğe bağlıdır; tam senkronizasyonu zorlar
--message-id: sync-message için zorunludur; senkronize edilecek belirli ileti ID'si
--workers: İsteğe bağlıdır; worker iş parçacığı sayısı
--help: Komut ve seçenek yardımını gösterir
SQLite şeması ve analiz örnekleri
- Oluşturulan SQLite veritabanındaki
messages tablosu, Gmail iletilerini analiz etmek için gereken alanları içerir
message_id: Benzersiz Gmail ileti ID'si
thread_id: Gmail ileti dizisi ID'si
sender: Ad ve e-posta içeren JSON gönderen bilgisi
recipients: to, cc, bcc türlerine göre alıcı JSON'u
labels: Gmail etiketleri dizisi
subject: İleti başlığı
body: Düz metin ileti gövdesi
size: Bayt cinsinden ileti boyutu
timestamp: İleti zamanı
is_read: Okunma durumu
is_outgoing: İletinin kullanıcı tarafından gönderilip gönderilmediği
is_deleted: İletinin Gmail'den silinip silinmediği
last_indexed: Son senkronizasyon zamanı
- Gönderene göre e-posta sayısı toplanabilir
SELECT sender->>'$.email', COUNT(*) AS count
FROM messages
GROUP BY sender->>'$.email'
ORDER BY count DESC
- Okunmamış e-postalar gönderene göre toplanarak ilgi çekmeyen çok sayıda e-posta gönderenler görülebilir
SELECT sender->>'$.email', COUNT(*) AS count
FROM messages
WHERE is_read = 0
GROUP BY sender->>'$.email'
ORDER BY count DESC
strftime kullanarak e-posta sayısı yıl, ay, gün, haftanın günü ve saat bazında toplanabilir
SELECT strftime('%Y', timestamp) AS period, COUNT(*) AS count
FROM messages
GROUP BY period
ORDER BY count DESC
- Gövdesinde
newsletter veya unsubscribe bulunan e-postalar bulunarak bültenler gönderen bazında gruplanabilir
SELECT sender->>'$.email', COUNT(*) AS count
FROM messages
WHERE body LIKE '%newsletter%' OR body LIKE '%unsubscribe%'
GROUP BY sender->>'$.email'
ORDER BY count DESC
- Gönderene göre toplam e-posta boyutu ve büyük e-posta gönderenleri MB cinsinden görülebilir
SELECT sender->>'$.email', sum(size)/1024/1024 AS size
FROM messages
GROUP BY sender->>'$.email'
ORDER BY size DESC
- Kendinize gönderdiğiniz e-posta sayısı,
recipients JSON'u ve sender e-posta koşuluyla hesaplanabilir
SELECT count(*)
FROM messages
WHERE EXISTS (
SELECT 1
FROM json_each(messages.recipients->'$.to')
WHERE json_extract(value, '$.email') = 'foo@example.com'
)
AND sender->>'$.email' = 'foo@example.com'
- Alınan e-postalar arasında gönderene göre toplam boyutu en yüksek olanlar görülebilir
SELECT sender->>'$.email', sum(size)/1024/1024 as total_size
FROM messages
WHERE is_outgoing=false
GROUP BY sender->>'$.email'
ORDER BY total_size DESC
- Silinen iletiler
is_deleted=1 koşuluyla sorgulanır
SELECT message_id, subject, timestamp
FROM messages
WHERE is_deleted=1
ORDER BY timestamp DESC
1 yorum
Hacker News yorumları
Şemada belirli header’ların neden ayrı çıkarıldığını merak ediyorum.
recipients,subject,senderJSON alanı olarak da tutulabilir; ama hepsi tek birheadersiçine konup mesajın kalan header’ları da orada saklanabilirPerformans yüzündense
headerstek bir JSON blob’u olarak tutulup gerekli alanlar generated column yapılabilir. Örneğinsubject,json_extract("headers", '$.Subject')ile oluşturulup indekslenebilirBu model güçlüydü; kullanıcı kendi sorguları için ihtiyaç duyduğu indeksli generated column’ları
ALTER TABLEile ekleyebiliyordu. DKIM durumu da"Dkim-Signature"çıkarılarak bir kolon ve indeks oluşturulduktan sonraGROUP BYile yapılabilirCREATE INDEX subjectidx ON messages(json_extract(headers, '$.Subject'))gibi oluşturursanız, ilgili ifadeye başvurulan yerlerde indeks kullanılırBu şekilde indeks oluşturduktan sonra ana tabloya
ALTERile generated column eklemek yerine, ilgili ifadeyi kullanan birVIEWoluşturmak daha kullanışlıydıGenelde sürekli kullanılacak kolonları ayrı çıkarmayı tercih ederim. E-posta header’ları gibi stabil bir hedef söz konusuysa bu daha da geçerli;
headerskolonu şema değişikliğini biraz kolaylaştırsa da yazma anındaki sıkıntıyı okuma anındaki sıkıntıya dönüştürür ve sessizce başarısız olma ihtimalini de bırakırYaklaşık iki ay sonra gerçekten gereken alanlar ortaya çıkınca JSON’dan dolduruyor, API’nin bunu güncel tutmasını sağlıyor ya da view oluşturuyorum. “Her şeyi MongoDB’ye atalım” veya “Dosya sisteminde bırakalım” yaklaşımından gelen büyüme sancılarını önlemede epey yardımcı oldu ve maliyeti de büyük değildi
dkimkolonunuNOT NULLolarak tanımlamışsınız; bir e-posta mesajındaDkim-Signatureheader’ı yoksa ne olacağını merak ediyorumBirkaç yıl önce Gmail benzeri büyük ölçekli e-posta görselleştirme aracı yapmıştım: https://github.com/terhechte/postsack
Boyut seçeneği de var mı merak ediyorum. Hangi gönderenin depolama alanımı en çok kullandığını görmek isterim. Ayrıca web sitesinin SSL sertifikası süresi dolmuş
Buna karşılık qdirstat cache file oluşturmak kolay, bu yüzden dosya gibi görünen çeşitli hedefleri görselleştirmek için kullanılabilir
Artık uygulamaya özel parolayla bile giriş yapılamaması, bir OAuth client oluşturup OAuth akışından geçmek zorunda olmak gerçekten üzücü. Kendi e-postam olmasına rağmen Google, erişebilmem için kullanılan açık standardı elimden aldı
Özellikle freelance e-postalarımın alıcı sistemlerde spam’e düştüğüne dair giderek daha fazla bilgi alıyorum. Yine de Google ekosistemine alışmış alışkanlıkları nasıl bırakacağım konusunda kararsızım
Yakın zamanda uygulamama https://github.com/rumca-js/Django-link-archive Gmail entegre etmeye çalıştım ama çok fazla zaman harcadım ve Gmail desteğinin buna değmeyeceğine karar verdim
Gmail to SQLite kimlik bilgisi kurulumunu 6 adımda anlatıyor, ama benim durumumda öyle olmadı. 6 adımdan sonra da Google uygulamanın yayımlanmadığını söyleyip yayımlamamı istedi; Workspace kullanıcısı olmadığım için uygulamayı dahili bırakamayacağımı söyledi; harici uygulamaya çevirince de doğrulamadan önce kullanılamayacağını söyledi
Doğrulama sürecinde domain, adres, diğer ayrıntılar, kapsamlar için gerekçe ve uygulamanın nasıl kullanıldığını açıklayan bir video bile istedi; gönderilen verileri doğrulamanın zaman alacağını söyledi. Tüm süreç bir ayar labirenti gibi ve kullanıcıların Google’ın istediği engelleri aşmasını beklemek fazlasıyla abartı
Şu anda var olan en iyi açık kaynak Gmail yedekleme yazılımının hangisi olduğunu merak ediyorum. Eklerin saklanması da dahil, böyle bir kurulum yapmış olan var mı merak ediyorum
Bu arada https://www.mailstore.com/en/products/mailstore-home/ da var. Açık kaynak değil ama indeksli bir GUI olduğu için yerel e-posta aramada iyi; devam ettirme yalnızca yedeklemede çalıştığından büyük ölçekli geri yüklemeler genelde başarısız oluyor
Birkaç ayda bir bunu çalıştırmamı hatırlatacak bir bildirim kurup yerel yedeği güncelliyorum. Hatırladığım kadarıyla gzip ile sıkıştırılmış mbox dosyası olarak geliyor
Bence bunun adı “Gmail to SQLite” değil, “IMAP to SQLite” gibi bir şey olmalı. Neden tek bir belirli e-posta sağlayıcısına bağlandığını anlamıyorum
IMAP çok daha zor ve çok daha yavaş; ayrıca Google’ın bant genişliği sınırlamalarına da takılıyor
Çok soğuk depolamada olduğu için zaman aşımına mı uğradı bilmiyorum. Bu yüzden Google’ın sahipli API’sini kullanmanın daha iyi çalışabileceğini anlıyorum
Bugünlerde Google Takeout mbox içeriyor, düzgün çalışıyor ve oldukça hızlı; ama sürekli güncelleme sağlamıyor. Sonunda başka bir e-posta sağlayıcısı olan Infomaniak’a taşındım ve geçmişte kendi posta alan adımı kullanmış olduğum için kendime teşekkür ettim
Tam metin arama da etkinleştirilebilse iyi olurdu
Dün ben de aynısından yaptım. Çünkü alıcı e-postalarını alan adına göre listelemek istiyordum. Kod berbat ama burada: https://github.com/hugoferreira/gmail-sqlite-db
PostgreSQL tabanlı IMAP sunucusu Archiveopteryx’i biraz hatırlatıyor: https://github.com/aox/aox
AOX’un şeması bana hep iyi görünmüştü ama gerçek anlamda düzgün kullanamadım. Ana kullanım amacı, günlük kullanılan bir IMAP sunucusu olmaktan çok posta analizi ve aramaydı
Burada bant genişliği maliyetinin nasıl olduğunu merak ediyorum. 40 GB’tan büyük Gmail hesabı olan biri olarak, bu araçla aktarım yaparsam ücretlendirilip ücretlendirilmeyeceğimi bilmek isterim
Düzeltmesi kolay. Google Takeout ücretsiz gibi göründüğüne göre önce indirip dosyayı ayrıştırmak yeterli. Yine de hemen başlamak açısından bu araç daha hızlı olur gibi