summaryrefslogtreecommitdiff
path: root/alot/account.py
diff options
context:
space:
mode:
Diffstat (limited to 'alot/account.py')
-rw-r--r--alot/account.py141
1 files changed, 115 insertions, 26 deletions
diff --git a/alot/account.py b/alot/account.py
index 6c832b21..fcce9639 100644
--- a/alot/account.py
+++ b/alot/account.py
@@ -18,15 +18,35 @@ Copyright (C) 2011 Patrick Totzke <patricktotzke@gmail.com>
"""
import mailbox
+import shlex
+import subprocess
+import logging
+import time
+import email
from urlparse import urlparse
from send import SendmailSender
class Account:
- def __init__(self, address, aliases=None, realname=None, gpg_key=None, signature=None,
- sender_type='sendmail', sendmail_command='sendmail',
- sent_mailbox=None):
+ """
+ Datastructure that represents an email account. It manages
+ this account's settings, can send and store mails to
+ maildirs (drafts/send)
+ """
+ address = None
+ """this accounts main email address"""
+ aliases = []
+ """list of alternative addresses"""
+ realname = None
+ """real name used to format from-headers"""
+ gpg_key = None
+ """gpg fingerprint :note:currently ignored"""
+ signature = None
+ """signature to append to outgoing mails note::currently ignored"""
+
+ def __init__(self, address=None, aliases=None, realname=None, gpg_key=None,
+ signature=None, sent_box=None, draft_box=None):
self.address = address
self.aliases = []
if aliases:
@@ -34,25 +54,90 @@ class Account:
self.realname = realname
self.gpg_key = gpg_key
self.signature = signature
- self.sender_type = sender_type
- self.mailbox = None
- if sent_mailbox:
+ self.sent_box = None
+ if sent_box:
mburl = urlparse(sent_mailbox)
if mburl.scheme == 'mbox':
- self.mailbox = mailbox.mbox(mburl.path)
+ self.sent_box = mailbox.mbox(mburl.path)
elif mburl.scheme == 'maildir':
- self.mailbox = mailbox.Maildir(mburl.path)
+ self.sent_box = mailbox.Maildir(mburl.path)
elif mburl.scheme == 'mh':
- self.mailbox = mailbox.MH(mburl.path)
+ self.sent_box = mailbox.MH(mburl.path)
elif mburl.scheme == 'babyl':
- self.mailbox = mailbox.Babyl(mburl.path)
+ self.sent_box = mailbox.Babyl(mburl.path)
elif mburl.scheme == 'mmdf':
- self.mailbox = mailbox.MMDF(mburl.path)
+ self.sent_box = mailbox.MMDF(mburl.path)
- if self.sender_type == 'sendmail':
- self.sender = SendmailSender(sendmail_command,
- mailbox=self.mailbox)
+ self.draft_box = None
+ if draft_box:
+ mburl = urlparse(sent_mailbox)
+ if mburl.scheme == 'mbox':
+ self.draft_box = mailbox.mbox(mburl.path)
+ elif mburl.scheme == 'maildir':
+ self.draft_box = mailbox.Maildir(mburl.path)
+ elif mburl.scheme == 'mh':
+ self.draft_box = mailbox.MH(mburl.path)
+ elif mburl.scheme == 'babyl':
+ self.draft_box = mailbox.Babyl(mburl.path)
+ elif mburl.scheme == 'mmdf':
+ self.draft_box = mailbox.MMDF(mburl.path)
+
+ def store_mail(self, mbx, mail):
+ """stores given mail in mailbox. if mailbox is maildir, set the S-flag.
+ :type mbx: `mailbox.Mailbox`
+ :type mail: `email.message.Message` or string
+ """
+ mbx.lock()
+ if isinstance(mbx, mailbox.Maildir):
+ msg = mailbox.MaildirMessage(email)
+ msg.set_flags('S')
+ else:
+ msg = mailbox.Message(email)
+ key = mbx.add(email)
+ mbx.flush()
+ mbx.unlock()
+
+ def store_sent_mail(self, mail):
+ """stores given mail as sent if sent_box is set"""
+ if self.sent_box:
+ self.store_mail(self.sent_box, mail)
+
+ def store_draft_mail(self, mail):
+ """stores given mail as draft if draft_box is set"""
+ if self.draft_box:
+ self.store_mail(self.sent_box, mail)
+
+ def send_mail(self, email):
+ """
+ sends given email
+ :returns: tuple (success, reason) of types bool and str.
+ """
+ return False, 'not implemented'
+
+
+class SendmailAccount(Account):
+ """Account that knows how to send out mails via sendmail"""
+ def __init__(self, cmd, **kwargs):
+ Account.__init__(self, **kwargs)
+ self.cmd = cmd
+
+ def send_mail(self, mail):
+ mail['Date'] = email.utils.formatdate(time.time(), True)
+ # no unicode in shlex on 2.x
+ args = shlex.split(self.cmd.encode('ascii'))
+ try:
+ proc = subprocess.Popen(args, stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out, err = proc.communicate(mail.as_string())
+ except OSError, e:
+ return False, str(e) + '. sendmail_cmd set to: %s' % self.cmd
+ if proc.poll(): # returncode is not 0
+ return False, err.strip()
+ else:
+ self.store_sent_mail(mail)
+ return True, ''
class AccountManager:
@@ -61,9 +146,10 @@ class AccountManager:
'aliases',
'gpg_key',
'signature',
- 'sender_type',
+ 'type',
'sendmail_command',
- 'sent_mailbox']
+ 'sent_box',
+ 'draft_box']
manditory = ['realname', 'address']
accountmap = {}
accounts = []
@@ -75,19 +161,22 @@ class AccountManager:
for s in accountsections:
options = filter(lambda x: x in self.allowed, config.options(s))
args = {}
+ to_set = self.manditory
for o in options:
args[o] = config.get(s, o)
- if o in self.manditory:
- self.manditory.remove(o)
- if not self.manditory:
- newacc = (Account(**args))
- self.accountmap[newacc.address] = newacc
- self.accounts.append(newacc)
- for alias in newacc.aliases:
- self.accountmap[alias] = newacc
+ if o in to_set:
+ to_set.remove(o) # removes obligation
+ if not to_set: # all manditory fields were present
+ sender_type = args.pop('type', 'sendmail')
+ if sender_type == 'sendmail':
+ cmd = args.pop('sendmail_command', 'sendmail')
+ newacc = (SendmailAccount(cmd, **args))
+ self.accountmap[newacc.address] = newacc
+ self.accounts.append(newacc)
+ for alias in newacc.aliases:
+ self.accountmap[alias] = newacc
else:
- pass
- # log info
+ logging.info('account section %s lacks fields %s' % (s, to_set))
def get_accounts(self):
"""return known accounts