mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-23 06:38:40 +02:00
182 lines
5.8 KiB
Python
182 lines
5.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import re
|
|
import time
|
|
import imaplib
|
|
from datetime import datetime, timedelta
|
|
from email.header import decode_header
|
|
import email.utils
|
|
from django.utils.translation import ugettext as _
|
|
from mailng.lib import decode, tables, imap_utf7
|
|
from mailng.lib.email_listing import MBconnector, EmailListing
|
|
from mailng.lib import tables, imap_utf7, parameters
|
|
|
|
|
|
class WMtable(tables.Table):
|
|
idkey = "imapid"
|
|
selection = tables.SelectionColumn("selection", first=True)
|
|
subject = tables.Column("subject", label=_("Subject"))
|
|
from_ = tables.Column("from", label=_("From"))
|
|
date = tables.Column("date", label=_("Date"))
|
|
flags = tables.ImgColumn("flags")
|
|
|
|
def parse(self, header, value):
|
|
try:
|
|
return getattr(IMAPheader, "parse_%s" % header)(value)
|
|
except AttributeError:
|
|
return value
|
|
|
|
class IMAPheader(object):
|
|
addr_exp = re.compile("([^<\(]+)<|\(([^>\)]+)>|\)")
|
|
name_exp = re.compile("\"(.+)\"")
|
|
|
|
@staticmethod
|
|
def parse_address(value):
|
|
m = IMAPheader.addr_exp.match(value)
|
|
if m:
|
|
name = m.group(1)
|
|
name = name.strip()
|
|
m2 = IMAPheader.name_exp.match(name)
|
|
if m2:
|
|
return IMAPheader.parse_subject(m2.group(1))
|
|
return IMAPheader.parse_subject(name)
|
|
return value
|
|
|
|
@staticmethod
|
|
def parse_address_list(values):
|
|
lst = values.split(",")
|
|
result = ""
|
|
for addr in lst:
|
|
if result != "":
|
|
result += ", "
|
|
result += IMAPheader.parse_address(addr)
|
|
return result
|
|
|
|
@staticmethod
|
|
def parse_from(value):
|
|
return IMAPheader.parse_address(value)
|
|
|
|
@staticmethod
|
|
def parse_to(value):
|
|
return IMAPheader.parse_address_list(value)
|
|
|
|
@staticmethod
|
|
def parse_cc(value):
|
|
return IMAPheader.parse_address_list(value)
|
|
|
|
@staticmethod
|
|
def parse_date(value):
|
|
ndate = datetime(*(email.utils.parsedate_tz(value))[:7])
|
|
now = datetime.now()
|
|
if now - ndate > timedelta(7):
|
|
return ndate.strftime("%d.%m.%Y %H:%M")
|
|
return ndate.strftime("%a %H:%M")
|
|
|
|
@staticmethod
|
|
def parse_subject(value):
|
|
res = ""
|
|
dcd = decode_header(value)
|
|
for part in dcd:
|
|
if res != "":
|
|
res += " "
|
|
res += part[0].strip(" ")
|
|
return decode(res)
|
|
|
|
class IMAPconnector(MBconnector):
|
|
def login(self, user, passwd):
|
|
import imaplib
|
|
|
|
try:
|
|
self.m = imaplib.IMAP4_SSL(self.address)
|
|
self.m.login(user, passwd)
|
|
except imaplib.IMAP4.error, test:
|
|
return False, test
|
|
return True, None
|
|
|
|
def _encodefolder(self, folder):
|
|
if not folder:
|
|
return "INBOX"
|
|
return folder.encode("imap4-utf-7")
|
|
|
|
def messages_count(self, folder=None):
|
|
(status, data) = self.m.select(self._encodefolder(folder))
|
|
(status, data) = self.m.sort("(REVERSE DATE)", "UTF-8", "(NOT DELETED)")
|
|
self.messages = data[0].split()
|
|
return len(self.messages)
|
|
|
|
def listfolders(self, topfolder='INBOX', md_folders=[]):
|
|
(status, data) = self.m.list()
|
|
result = []
|
|
for mb in data:
|
|
attrs, truc, name = mb.split()
|
|
name = name.strip('"').decode("imap4-utf-7")
|
|
present = False
|
|
for mdf in md_folders:
|
|
if mdf["name"] == name:
|
|
present = True
|
|
break
|
|
if not present:
|
|
result += [name]
|
|
return sorted(result)
|
|
|
|
def fetch(self, start=None, stop=None, folder=None, all=False):
|
|
if not start and not stop:
|
|
return []
|
|
result = []
|
|
self.m.select(self._encodefolder(folder), True)
|
|
if start and stop:
|
|
submessages = self.messages[start - 1:stop]
|
|
range = ",".join(submessages)
|
|
else:
|
|
submessages = [start]
|
|
range = start
|
|
if not all:
|
|
query = '(FLAGS BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)])'
|
|
else:
|
|
query = '(RFC822)'
|
|
typ, data = self.m.fetch(range, query)
|
|
if not folder:
|
|
folder = "INBOX"
|
|
tmpdict = {}
|
|
for response_part in data:
|
|
if isinstance(response_part, tuple):
|
|
imapid = response_part[0].split()[0]
|
|
flags = imaplib.ParseFlags(response_part[0])
|
|
msg = email.message_from_string(response_part[1])
|
|
msg["imapid"] = "%s/%s" % (folder, imapid)
|
|
if not "\\Seen" in flags:
|
|
msg["class"] = "unseen"
|
|
if "\\Answered" in flags:
|
|
msg["img_flags"] = "/static/pics/answered.png"
|
|
tmpdict[imapid] = msg
|
|
for id in submessages:
|
|
result += [tmpdict[id]]
|
|
return result
|
|
|
|
class ImapListing(EmailListing):
|
|
tpl = "webmail/index.html"
|
|
|
|
def __init__(self, user, password, baseurl=None, **kwargs):
|
|
self.mbc = IMAPconnector(parameters.get("webmail", "SERVER_ADDRESS"), 143)
|
|
status, text = self.mbc.login(user, password)
|
|
if not status:
|
|
print "Login error: %s" % text
|
|
EmailListing.__init__(self, **kwargs)
|
|
if baseurl:
|
|
self.paginator.baseurl = baseurl
|
|
|
|
def getfolders(self):
|
|
md_folders = [{"name" : "INBOX", "icon" : "overview.png"},
|
|
{"name" : 'Drafts'},
|
|
{"name" : 'Junk'},
|
|
{"name" : 'Sent'},
|
|
{"name" : 'Trash', "icon" : "trash.png"}]
|
|
folders = self.mbc.listfolders(md_folders=md_folders)
|
|
for fd in folders:
|
|
md_folders += [{"name" : fd}]
|
|
return md_folders
|
|
|
|
def fetch(self, id_start, id_stop):
|
|
return WMtable(self.mbc.fetch(start=id_start, stop=id_stop,
|
|
folder=self.folder))
|