Commits

Anonymous committed 03c0d4c

[svn] Added webhelpers.mail and webhelpers.time modules and incremented version number

Comments (0)

Files changed (3)

 
 setup(
     name="WebHelpers",
-    version='0.1',
+    version='0.1.1',
     description='Web Helpers',
     long_description="""
 Web Helpers is a library of helper functions intended to make writing templates in web

webhelpers/mail.py

+"""Simple function to send email ported from pythonweb.org web.mail by James Gardner <james@jimmyg.org>
+    
+The mail module provides a simple function ``mail()`` which can be used to send emails as shown in the example below::
+
+    mail(
+        msg        = "Hello!",
+        to         = 'james@example.com',
+        reply_name  = 'James Gardner',
+        reply_email = 'james@example.com',
+        subject    = 'Test Email',
+        sendmail   = '/usr/bin/sendmail',
+        method     = 'sendmail'
+    )
+
+To send the same email via SMTP instead of using Sendmail you would use::
+
+    mail(
+        msg        = "Hello James!",
+        to         = 'james@example.com',
+        reply_name  = 'James Gardner',
+        reply_email = 'james@example.com',
+        subject    = 'Test Email',
+        smtp       = 'smtp.ntlworld.com',
+        method     = 'smtp'
+    )
+
+If you get an error like ``socket.error: (10060, 'Operation timed out')`` it is likely that the SMTP address you specified either doesn't exist or will not give you access.
+
+Function definition for mail():
+
+    ``msg``
+        Text of the message
+
+    ``to``
+        A list of recipient addresses in the form: addr@addr.com
+
+    ``subject``
+        Email subject line, defualts to empty string ``''``.
+
+    ``method``
+        Describes which method to use to send the email. Can be ``'smtp'`` or ``'sendmail'`` but ``method`` only needs to be specified if both ``smtp`` and ``sendmail`` parameters are specified otherwise the method that is defined is used and the value of ``method`` is ignored.
+
+    ``smtp``
+        SMTP server address
+
+    ``sendmail``
+        Sendmail path
+
+    ``blind``
+        Should be set to ``True`` if recipients are to be blocked from seeing who else the email was sent to (ie recipeints are bcc'd)
+
+    ``reply_name``
+        The name of the person sending the email. Only available if ``reply`` is not specified.
+
+    ``reply_email``
+        The email address of the person sending the email. Only available if ``reply`` is not specified.
+
+    ``reply``
+        The name and email address of the person sending the email in the form: ``"sender name <addr@example.com>"``. Should only be specified if ``reply_name`` and ``reply_email`` are not specified.
+
+    ``type``
+        The second part of the content-type, eg ``'plain'`` for a plain text email, ``'html'`` for an HTML email.
+
+The module also provides a method ``build_reply()`` which can be used to put the name and email address into the format required for the ``reply`` parameter of the ``mail()`` helper::
+
+    >>> mail.build_reply('James Gardner, 'james@example.com')
+    James Gardner <james@example.com>
+    
+    
+For more advanced functionality look at the modules included with the Python standard library.
+"""
+
+def build_reply(name, email):
+    return '%s <%s>'%(name, email)
+    
+def mail(**params):#msg, me, to, subject, smtpServer, blind=False
+    """Function to send a text only email via SMTP.
+        msg         - Text of the message.
+        to          - A list of recipient email addresses in the form: addr@addr.com.
+        subject     - Email subject.
+        smtp        - SMTP server address.
+        sendmail    - Sendmail path.
+        method      - Which method to use if smtp or sendmail aren't specified.
+        blind       - Whether to send the emails blind or not.
+        reply       - The name and address of the person sending the email in the form: "sender name <addr@example.com>"
+        reply_name
+        reply_email
+        type        - The second part of the content-type, eg 'plain' for 'Content-type: text/plain\n\n'
+    """
+    # imports
+    import StringIO
+    import smtplib
+    from email.MIMEText import MIMEText
+    from email.MIMEBase import MIMEBase
+    import email.Utils
+    
+    if params.has_key('reply_name') and not params.has_key('reply_email'):
+        raise Exception("You must specify a 'reply_email' as well as a 'reply_name'.")
+    elif params.has_key('reply_email') and not params.has_key('reply_name'):
+        raise Exception("You must specify a 'reply_name' as well as a 'reply_email'.")
+    if params.has_key('reply') and (params.has_key('reply_email') or params.has_key('reply_name')):
+        raise Exception("You cannot specify 'reply' as well as a 'reply_name' and 'reply_email'.")
+    if not params.has_key('reply'):
+        params['reply'] = "%s <%s>"%(params['reply_name'], params['reply_email'])
+    
+    if not params.has_key('blind'):
+        params['blind'] = False
+    if params['blind'] not in [True, False]:
+        raise Exception("'blind' can only be True or False.")
+    # Make sure the essential attributes are there
+    for p in ['msg', 'to', 'subject']:
+        if not params.has_key(p):
+            raise Exception("You must specify the attribute '%s' to send an email."%p)
+    # Make sure they are stings
+    for p in ['msg', 'subject']:
+        if type(params[p]) <> type(''):
+            raise Exception("The attribute '%s' must be a string."%p)
+    # Check method
+    if not (params.has_key('smtp') or params.has_key('sendmail')) and not params.has_key('method'):
+        raise Exception("You must specify an SMTP server or sendmail path")
+    if not params.has_key('method'):
+        if params.has_key('smtp') and params.has_key('sendmail'):
+            raise Exception("You must specify which method you want to use to send the email")
+        elif params.has_key('smtp'):
+            params['method'] = 'smtp'
+        else:
+            params['method'] = 'sendmail'
+    if params['method'] not in ['sendmail','smtp']:
+        raise Exception("The method parameter cannot be '%s'."%params['method'])
+    # Open a plain text file for reading.  For this example, assume that
+    # the text file contains only ASCII characters.
+    fp = StringIO.StringIO(params['msg'])
+    if not params.has_key('type'):
+        msg = MIMEText(fp.read())
+    else:
+        msg = MIMEBase('text',params['type'])
+        msg.set_payload(fp.read())
+    fp.close()
+    msg['From'] = params['reply']
+    msg['Subject'] = params['subject']
+    if type(params['to']) == type(''):
+        params['to']=[params['to']]
+    if params['method'] == 'sendmail':
+        if params['blind'] == True:
+            msg['Bcc'] = ', '.join(params['to'])
+        else:
+            msg['To'] = ', '.join(params['to'])
+        import os
+        if not os.path.exists(params['sendmail']):
+            raise Exception("The path '%s' doesn't exist. Please check the location of sendmail."%params['sendmail'])
+        fp = os.popen(params['sendmail']+" -t", 'w')
+        fp.write(msg.as_string())
+        error = fp.close()
+        if error:
+            raise Exception("Error sending mail: Sendmail Error '%s'."% error)
+    elif params['method'] == 'smtp':
+        if params['blind'] == True:
+            msg['To'] = ''
+        else:
+            msg['To'] = ', '.join(params['to'])
+        # Send the message via our own SMTP server, but don't include the
+        # envelope header.
+        s = smtplib.SMTP()
+        #s.set_debuglevel(100) 
+        s.connect(params['smtp'])
+        result = s.sendmail(params['reply'], params['to'], msg.as_string())
+        s.quit()
+        if result:
+            for r in result.keys():
+                error+= "Error sending to"+ str(r)
+                rt = result[r]
+                error+= "Code"+ str(rt[0])+":"+ str(rt[1])
+            raise Exception("Error sending mail: %s"% error)

webhelpers/time.py

+"""Time module from web.util.time for turning a string into seconds based on code submited to the PythonWeb mailing list by Felix Schwartz and adapted by James Gardner
+
+Usage::
+
+    >>> from webhelpers.time import seconds
+    >>> print seconds('10sec')
+    10
+    >>> print seconds('4hr')
+    1440
+
+"""
+
+import re, string
+
+class Time:
+    
+    def __init__(self):
+        self.seconds=['s','sec','seconds','seconds']
+        self.minutes=['min','minute','mins','minutes']
+        self.hours=['hr','hours','hour']
+        self.days=['day','days','d']
+        self.weeks=['w','week','weeks']
+        self.months=['month','months','mon']
+        
+    def getSeconds(self, parameter):
+        if parameter in self.seconds:   return 1
+        elif parameter in self.minutes: return 60
+        elif parameter in self.hours:   return 60 * 60
+        elif parameter in self.days:    return 60 * 60 * 24
+        elif parameter in self.weeks:   return 60 * 60 * 24 * 7
+        elif parameter in self.months:  return 60 * 60 * 24 * 30
+        else: return 0
+    
+    def convertIntoSeconds(self, age):
+        if age == None or age == '': return 0
+        if re.match('\d+$', age): return int(age)
+        match = re.match('(\d+)(' + string.join(self.seconds + self.minutes + self.hours + self.days + self.weeks + self.months, '|') + ')$', age)
+        if match != None:
+            number = int(match.group(1))
+            return number * self.getSeconds(match.group(2))
+        return -1
+        
+def seconds(value):
+    t = Time()
+    v = t.convertIntoSeconds(str(value))
+    if v == -1:
+        raise Exception('Invalid time, %s'%repr(value))
+    return v
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.