summaryrefslogtreecommitdiff
path: root/fake-service/app/adapter/mail_service.py
blob: 2825af9d0d338c854ba1603ea737bc182a7ed736 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#
# Copyright (c) 2014 ThoughtWorks, Inc.
#
# Pixelated is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pixelated is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
import os
import re
import mailbox

from tagsset import TagsSet
from mailset import MailSet
from contacts import Contacts
from mail import Mail


class MailService:
    MAILSET_PATH = os.path.join(os.environ['HOME'], 'mailsets', 'mediumtagged')

    def __init__(self):
        self.mailset = MailSet()
        self.tagsset = TagsSet()
        self.contacts = Contacts()

    def reset(self):
        self.mailset = MailSet()
        self.tagsset = TagsSet()
        self.contacts = Contacts()

    def _read_file(self, filename):
        with open(filename, 'r') as fd:
            return fd.read()

    def _create_message_from_file(self, filename):
        data = self._read_file(filename)
        return self.create_message_from_string(data, filename)

    def create_message_from_string(self, data, filename=None):
        if data.startswith('From '):
            msg = mailbox.mboxMessage(data)
            from_addr = re.sub(r"^From ", "", msg.get_unixfrom())
            msg.from_addr = from_addr
            msg.set_from(from_addr)
        else:
            msg = mailbox.Message(data)
            msg.from_addr = msg.get('From')
        return msg

    def _create_message_from_string(self, data):
        return mailbox.Message(data)

    def load_mailset(self):
        mbox_filenames = [
            filename
            for filename in os.listdir
            (self.MAILSET_PATH) if filename.startswith('mbox')]
        messages = (self._create_message_from_file(os.path.join(self.MAILSET_PATH, mbox))
                    for mbox in mbox_filenames)

        self.index_messages(messages)

    def index_messages(self, messages):
        for message in messages:
            self.mailset.add(message)
            self.tagsset.add(message)
            self.contacts.add(message)

    def mails(self, query, page, window_size):
        mails = self.mailset.values()
        mails = [mail for mail in mails if query.test(mail)]
        return sorted(mails, key=lambda mail: mail.date, reverse=True)

    def mail(self, mail_id):
        return self.mailset.get(mail_id)

    def search_contacts(self, query):
        return self.contacts.search(query)

    def mark_as_read(self, mail_id):
        self.mailset.mark_as_read(mail_id)
        self.tagsset.mark_as_read(self.mail(mail_id).tags)

    def delete_mail(self, mail_id):
        purged = self.mailset.delete(mail_id)
        if not purged:
            self.tagsset.increment_tag_total_count('trash')

    def update_tags_for(self, mail_id, new_tags):
        mail = self.mail(mail_id)

        new_tags_set = set(new_tags)
        old_tags_set = set(mail.tags)

        increment_set = new_tags_set - old_tags_set
        decrement_set = old_tags_set - new_tags_set

        map(lambda x: self.tagsset.increment_tag_total_count(x), increment_set)
        map(lambda x: self.tagsset.decrement_tag_total_count(x), decrement_set)

        mail.tags = new_tags

    def send(self, mail):
        mail = Mail.from_json(mail)
        self.mailset.update(mail)
        self.tagsset.increment_tag_total_count('sent')
        self.tagsset.decrement_tag_total_count('drafts')
        return mail.ident

    def save_draft(self, mail):
        mail = self.mailset.add_draft(Mail.from_json(mail))
        return mail.ident

    def update_draft(self, mail):
        mail = Mail.from_json(mail)
        self.mailset.update(mail)
        return mail.ident

    def draft_reply_for(self, mail_id):
        return self.mailset.find(draft_reply_for=mail_id)