You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.7 KiB
Python

import email.header
import imaplib
import imapclient
from bureau import Bureau, add_command, add_api
class Message(object):
"""
This is just a convenience class for holding email message data.
It could be fancier some day but for now this seems fine.
"""
pass
class MailRoom(Bureau):
"""
The Mail Room handles (electronic) post for the other Bureaus of
the Screenless Office.
"""
name = "Mail Room"
prefix = "PO"
version = 0
def __init__(self):
Bureau.__init__(self)
# TODO: multiple accounts / folders
if "user" in self.config:
self.login = self.config["user"]["login"]
self.password = self.config["user"]["password"]
self.host = self.config["user"]["host"]
self.spamfolder = self.config["user"]["spamfolder"]
self.trashfolder = self.config["user"]["trashfolder"]
self.imap_ssl = self.config["user"]["ssl"]
if self.imap_ssl.lower() == "true":
self.imap_ssl = True
else:
self.imap_ssl = False
self.imapserv = imapclient.IMAPClient(self.host, use_uid=True, ssl=self.imap_ssl)
self.imapserv.login(self.login, self.password)
self.imapserv.select_folder("INBOX")
else:
print("you need to configure an IMAP account!")
print("add a [user] section to PO.ini with:")
print(" login = mylogin")
print(" password = mypassword")
print(" host = my.imap.server.address.com")
# setup db's for mapping short codes to IMAP msg ids (and reversed)
self.postdb = self.dbenv.open_db(b"postdb")
self.postdb_rev = self.dbenv.open_db(b"postdb_rev")
def _connect_imap(self):
try:
self.imapserv.select_folder("INBOX")
except imaplib.error:
self.imapserv.login(self.login, self.password)
def get_imap_id(self, msgid):
"""
take short code and look up the IMAP message id
"""
with self.dbenv.begin(db=self.postdb) as txn:
imap_id = txn.get(msgid.encode())
return int(imap_id)
@add_command("fax", "Send a Document Camera Image via Email")
def fax(self, data):
"""
Takes a photograph using the document camera and sends it in an E-mail.
"""
photo = self.send("PXphoto.")
@add_command("r", "Print full email")
def read(self, data):
"""
Prints out the full detailed version of an email.
"""
shortcode, _ = data.split(".")
imap_id = self.get_imap_id(shortcode)
self._connect_imap()
resp = self.imapserv.fetch([imap_id], ['ENVELOPE', 'INTERNALDATE'])
msg = Message()
# msg.to = resp[imap_id][]
self.imapserv.add_flags(imap_id, [imapclient.SEEN])
# self.print_full("email.html", msg=msg, shortcode=shortcode)
@add_command("d", "Delete email")
def delete(self, data):
"""
Deletes an email and moves it to the trash folder.
"""
shortcode, _ = data.split(".")
imap_id = self.get_imap_id(shortcode)
self._connect_imap()
self.imapserv.add_flags(imap_id, [imapclient.SEEN])
self.imapserv.copy((imap_id), self.trashfolder)
self.imapserv.delete_messages((imap_id))
self.imapserv.expunge()
@add_command("sp", "Mark as spam")
def mark_spam(self, data):
"""
Flags an email as spam, mark as read and move it to the configured SPAM
folder.
"""
shortcode, _ = data.split(".")
imap_id = self.get_imap_id(shortcode)
self._connect_imap()
self.imapserv.add_flags(imap_id, [imapclient.SEEN])
self.imapserv.copy((imap_id), self.spamfolder)
self.imapserv.delete_messages((imap_id))
self.imapserv.expunge()
@add_command("re", "Reply with scan")
def reply_scan(self, data):
"""
Reply to the sender of a mail with the PDF currently queued in the
document scanner.
"""
# look up short code to get IMAP ID
# extract the sender and title
# put together the reply
pass
@add_api("unread", "Get unread mails")
def unread(self):
"""
Polls the currently configured IMAP server and returns a dict
containing unread emails.
"""
messages = self.imapserv.sort("ARRIVAL", ["UNSEEN"])
print("%d unread messages in INBOX" % len(messages))
return self.imapserv.fetch(messages, ['FLAGS', 'INTERNALDATE',
'ENVELOPE', 'RFC822.SIZE'])
def main():
mr = MailRoom()
mr.run()
if __name__ == "__main__":
main()