Source code for i3pystatus.mail.imap
from i3pystatus.core.util import require, internet
try:
from imaplib2.imaplib2 import IMAP4, IMAP4_SSL
use_idle = True
except ImportError:
from imaplib import IMAP4, IMAP4_SSL
use_idle = False
import contextlib
import time
import socket
from threading import Thread
from i3pystatus.mail import Backend
IMAP_EXCEPTIONS = (socket.error, socket.gaierror, IMAP4.abort, IMAP4.error)
[docs]class IMAP(Backend):
"""
Checks for mail on a IMAP server
"""
settings = (
"host", "port",
"username", "password",
('keyring_backend', 'alternative keyring backend for retrieving credentials'),
"ssl",
"mailbox",
)
required = ("host", "username", "password")
keyring_backend = None
port = 993
ssl = True
mailbox = "INBOX"
imap_class = IMAP4
connection = None
last = 0
def init(self):
if self.ssl:
self.imap_class = IMAP4_SSL
if use_idle:
self.thread = Thread(target=self._idle_thread)
self.daemon = True
self.thread.start()
@contextlib.contextmanager
def ensure_connection(self):
try:
if self.connection:
self.connection.select(self.mailbox)
if not self.connection:
self.connection = self.imap_class(self.host, self.port)
self.connection.login(self.username, self.password)
self.connection.select(self.mailbox)
yield
except IMAP_EXCEPTIONS:
# NOTE(sileht): retry just once if the connection have been
# broken to ensure this is not a sporadic connection lost.
# Like wifi reconnect, sleep wake up
try:
self.connection.close()
except IMAP_EXCEPTIONS:
pass
try:
self.connection.logout()
except IMAP_EXCEPTIONS:
pass
# Wait a bit when disconnection occurs to not hog the cpu
time.sleep(1)
self.connection = None
def _idle_thread(self):
# update mail count on startup
with self.ensure_connection():
self.count_new_mail()
while True:
with self.ensure_connection():
# Block until new mails
self.connection.idle()
# Read how many
self.count_new_mail()
def count_new_mail(self):
self.last = len(self.connection.search(None, "UnSeen")[1][0].split())
@property
@require(internet)
def unread(self):
if not use_idle:
with self.ensure_connection():
self.count_new_mail()
return self.last
Backend = IMAP