# -*- coding: utf-8 -*- """ The mailjam project - mta.py This file is released under the BSD license, see LICENSE for more information. Francisco de Borja Lopez Rio - Soluciones Informaticas Codigo23 S.L.U. - http://codigo23.net """ import os, sys, email, smtplib, xmlrpclib from datetime import datetime from mailjam.models import MailingList from mailjam.config import MTAClientConfig from mailjam.tools import validate_email_address class MTAClient(): def __init__(self, address=None, configfile=None): if not validate_email_address(address): raise ValueError(address, ' is not a valid email address') mta_config = MTAClientConfig(configfile=configfile) mta_config.load() self.config = mta_config.config self.rpc = xmlrpclib.ServerProxy(self.config['server']['uri']) self.address = self._validate_address(address) self.suscriptors = self.rpc.members.list(address) self.reply_to = self.address self.raw_email = None self.queue = [] def _validate_archive_path(self): """ Validate that the archive path exists. If not, try to create it """ if not os.path.exists(self.config['archive']['path']): # FIXME: This will raise an IOError if the user has no # privileges to create the directory, perhaps we should catch # that and show an error instead os.makedirs(self.config['archive']['path']) return True def _validate_address(self, address=None): """ The address provided by the user will be valid only if it is a valid email address and if it is the email address of an already existing mailing list """ if not validate_email_address(address): raise ValueError(address, ' is not a valid email address') if not address in self.rpc.lists.addresses(): raise ValueError(address, ' is not the address of any existing mailing list') # If it is valid, return it return address def get_raw_email(self, raw_email=None): """ get the raw data containing email information. If raw_email is None, try to get the data from stdin """ if not raw_email: try: self.raw_email = sys.stdin.read() except: raise IOError('Can not get a valid email from stdin') else: self.raw_email = raw_email # FIXME: We should perform some checks on the raw data, ensuring # it is a valid email text return self.raw_email def save_raw_email(self): if not self.raw_email: # FIXME: perhaps a while loop here, with some maximum recursion # check, would be nice here self.get_raw_email() # Check the path to the archive exists self._validate_archive_path() filename = os.path.join(self.config['archive']['path'], datetime.today().strftime('%Y%d%m%H%M%S%f')) tmpfile = file(filename, 'w') tmpfile.write(self.raw_email) tmpfile.close() self.queue.append(filename) def send_email(self): """ Send emails from the queue, if there is any """ if self.queue: next_email = self.queue.pop() email_file = file(next_email, 'r') email_data = email.message_from_file(email_file) email_file.close() email_data['Reply-to'] = self.reply_to smtp_conn = smtplib.SMTP() smtp_conn.connect() smtp_conn.sendmail(email_data['From'], self.suscriptors, email_data.as_string()) smtp_conn.close() # FIXME: enable tmp data removal here: # if not self.config['archive']['persistent']: # REMOVE THE FILE FROM DISK def run(self): self.save_raw_email() self.send_email()