Sendto

From Enso Wiki

Jump to: navigation, search
  • NOTE: This command is written for Command Server not as a stand alone command

Contents

[edit] Usage

  • sendto {email} - It will take any file or selection of files and send them as attachments to given email address.

Since Enso doesn't allow to type '@' character at the moment, you should use '?' instead. It will be replaced by '@' automatically.

Example:

sendto foo?bar.com

or, if auto-domain (see below) is enabled:

sendto foo?bar

[edit] Installation

  • Create file command_sendto.py containing the code below. Put it into commands/ directory in Command Server directory.
  • Create file command_sendto.ini and put it into config/ directory in Command Server directory.

[edit] Configuration

  • Example command_sendto.ini file:
[options]
auto-domain=True
domain=com
 
[smtp]
server=localhost
 
[email]
sender=foo@bar.com
subject=File(s) for you
text=There are the files...
  • smtp and email sections are most important.
  • If auto-domain is true, it is enough to use shortened email like foo@bar and in such case, domain will be append automatically.

[edit] Code

from base import BaseCommand
 
class Command(BaseCommand):
    def __init__(self, *args):
        BaseCommand.__init__(self, *args)
 
        self.newArbitraryCommand("sendto {email}", self._sendCommand, "Send file(s) as attachment to email address. Use '?' in place of '@'.", "Send file(s) as attachment to email address. Use '?' in place of '@'.")
        
        #config = self.__loadConfig("config/command_sendto.ini")
        #print "SMTP server: " + config['smtp.server']
        #print "SMTP sender: " + config['email.sender']
 
    def _sendCommand(self, email):
        config = self.__loadConfig("config/command_sendto.ini")
        #print "SMTP server: " + self._config['smtp.server']
        #print "SMTP sender: " + self._config['email.sender']
        autoGuessDomain = config['options.auto-domain'].lower() == 'true' or config['options.auto-domain'].lower() == 'yes' or config['options.auto-domain'] == '1'
        autoDomain = config['options.domain']
        #print "Auto guess domain: " + str(autoGuessDomain)
        #print "Auto domain: " + autoDomain
 
        files = self.getFileSelection()
        if len(files) == 0:
            self.displayMessage("No files selected!")
            return
        
        fileCount = len(files)
        fileName = None
        # If there was only one file, get its name
        if fileCount == 1:
            # Get just filename and extension
            fileNameParts = files[0].rpartition('\\')
            if fileNameParts[1] != None:
                fileName = fileNameParts[2]
                fileNameParts = fileName.rpartition('.')
                # If filename itself is longer than 20 chars, shorten it for display
                if fileNameParts[1] != None and len(fileNameParts[0]) > 20:
                    fileName = fileNameParts[0][:20] + '...' + fileNameParts[2]
            else:
                fileName = fileNameParts[2]
            print fileName
 
        # Check email validity
        if not email:
            self.displayMessage("Email can't be empty!")
            return
        if email.find('?') == -1:
            self.displayMessage("Email format is not valid! Use '?' in place of '@'.")
            return
        # Replace ? with @
        email = email.strip().lower().replace('?', '@', 1)
        # If auto-domain is on, append domain of not there
        if autoGuessDomain and autoDomain and email.rfind('.' + autoDomain, email.find('@')) == -1:
            email = email + '.' + autoDomain
 
        emailTest = self.__isValidEmail(email)
        if not emailTest[0]:
            self.displayMessage(emailTest[1], "Email format is not valid!")
            return
 
        if fileCount == 1 and fileName:
            self.displayMessage("Sending file '" + fileName + "' to " + email)
        else:
            self.displayMessage("Sending " + str(fileCount) + " files to " + email)
 
        # Send the mail with attachment(s)
        try:
            result = self._sendMail(
                    config['email.sender'], 
                    [email], 
                    config['email.subject'],
                    config['email.text'],
                    files, 
                    config['smtp.server'])
        except:
            result = -1
 
        # Report to user
        if result == -1:
            self.displayMessage("Error sending the message!")
        elif result == 1:
            self.displayMessage("Error opening the file for reading!")
        elif result == 0:
            if fileCount == 1:
                self.displayMessage("", "File has been sent.")
            else:
                self.displayMessage("", "Files have been sent.")
 
    def _sendMail(self, send_from, send_to, subject, text, files=[], server="localhost"):
        import smtplib
        import os
        from email.MIMEMultipart import MIMEMultipart
        from email.MIMEBase import MIMEBase
        from email.MIMEText import MIMEText
        from email.Utils import COMMASPACE, formatdate
        from email import Encoders
 
        assert type(send_to)==list
        assert type(files)==list
 
        msg = MIMEMultipart()
        msg['From'] = send_from
        msg['To'] = COMMASPACE.join(send_to)
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject
 
        msg.attach( MIMEText(text) )
 
        for f in files:
            part = MIMEBase('application', "octet-stream")
            try:
                part.set_payload( open(f, "rb").read() )
            except:
                return 1
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
            msg.attach(part)
 
        smtp = smtplib.SMTP(server)
        smtp.sendmail(send_from, send_to, msg.as_string())
        smtp.close()
        return 0
 
    def __isValidEmail(self, email):
        import re
        if not email:
            return False,"Email is empty"
        email = email.strip().lower()
        if email.count(' ') > 0:
            return False,"Email contains spaces"
        _badchars = re.compile(r'[][()<>|;^,/\200-\377]')
        if _badchars.search(email) or email[0] == '-':
            return False,"Email contains forbidden character(s)"
        user = None
        domain_parts = None
        at_sign = email.find('@')
        if at_sign < 1:
            user = email
        else:
            user = email[:at_sign]
            rest = email[at_sign+1:]
            domain_parts = rest.split('.')
        if not domain_parts:
            return False,"Email is missing domain part"
        if len(domain_parts) < 2:
            return False,"Domain part is too short"
        return True,"OK"
 
    def __loadConfig(self, file):
        import ConfigParser
        config = {
            'options.auto-domain':'false',
            'options.domain':'com',
            'email.sender':'unknown',
            'email.subject':'File(s)',
            'email.text':'There are the files',
            'smtp.server':'localhost'
        }
        cf = open(file, "r")
        cp = ConfigParser.ConfigParser()
        cp.readfp(cf)
        for sec in cp.sections():
            name = sec.lower()
            for opt in cp.options(sec):
                config[name + "." + opt.lower()] = cp.get(sec, opt).strip()
        return config
 
# vim:set tabstop=4 shiftwidth=4 expandtab

[edit] Contact

Contact me in case of any ideas/bugs/suggestions --Blackdaemon 11:07, 11 February 2008 (PST)