[Python-modules-commits] [python-mailer] 01/02: Imported Upstream version 0.8.1

Hugo Lefeuvre hle at moszumanska.debian.org
Fri Aug 19 08:51:13 UTC 2016


This is an automated email from the git hooks/post-receive script.

hle pushed a commit to branch master
in repository python-mailer.

commit e2885089f4a3270e8b8fd091f92910de3c539e0b
Author: Hugo Lefeuvre <hle at debian.org>
Date:   Fri Aug 19 10:32:41 2016 +0200

    Imported Upstream version 0.8.1
---
 PKG-INFO                             |  18 ++
 mailer.egg-info/PKG-INFO             |  18 ++
 mailer.egg-info/SOURCES.txt          |   6 +
 mailer.egg-info/dependency_links.txt |   1 +
 mailer.egg-info/top_level.txt        |   1 +
 mailer.py                            | 480 +++++++++++++++++++++++++++++++++++
 setup.cfg                            |   5 +
 setup.py                             |  28 ++
 8 files changed, 557 insertions(+)

diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..6515890
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,18 @@
+Metadata-Version: 1.1
+Name: mailer
+Version: 0.8.1
+Summary: A module to send email simply in Python
+Home-page: https://bitbucket.org/ginstrom/mailer
+Author: Ryan Ginstrom
+Author-email: ryan at ginstrom.com
+License: MIT License
+Description: UNKNOWN
+Keywords: email,smtp
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
diff --git a/mailer.egg-info/PKG-INFO b/mailer.egg-info/PKG-INFO
new file mode 100644
index 0000000..6515890
--- /dev/null
+++ b/mailer.egg-info/PKG-INFO
@@ -0,0 +1,18 @@
+Metadata-Version: 1.1
+Name: mailer
+Version: 0.8.1
+Summary: A module to send email simply in Python
+Home-page: https://bitbucket.org/ginstrom/mailer
+Author: Ryan Ginstrom
+Author-email: ryan at ginstrom.com
+License: MIT License
+Description: UNKNOWN
+Keywords: email,smtp
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
diff --git a/mailer.egg-info/SOURCES.txt b/mailer.egg-info/SOURCES.txt
new file mode 100644
index 0000000..27a9c7b
--- /dev/null
+++ b/mailer.egg-info/SOURCES.txt
@@ -0,0 +1,6 @@
+mailer.py
+setup.py
+mailer.egg-info/PKG-INFO
+mailer.egg-info/SOURCES.txt
+mailer.egg-info/dependency_links.txt
+mailer.egg-info/top_level.txt
\ No newline at end of file
diff --git a/mailer.egg-info/dependency_links.txt b/mailer.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/mailer.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/mailer.egg-info/top_level.txt b/mailer.egg-info/top_level.txt
new file mode 100644
index 0000000..f2ae723
--- /dev/null
+++ b/mailer.egg-info/top_level.txt
@@ -0,0 +1 @@
+mailer
diff --git a/mailer.py b/mailer.py
new file mode 100644
index 0000000..1aa8e94
--- /dev/null
+++ b/mailer.py
@@ -0,0 +1,480 @@
+#coding: UTF8
+"""
+mailer module
+
+Simple front end to the smtplib and email modules,
+to simplify sending email.
+
+A lot of this code was taken from the online examples in the
+email module documentation:
+http://docs.python.org/library/email-examples.html
+
+Released under MIT license.
+
+Version 0.5 is based on a patch by Douglas Mayle
+
+Sample code:
+
+    import mailer
+
+    message = mailer.Message()
+    message.From = "me at example.com"
+    message.To = "you at example.com"
+    message.RTo = "you at example.com"
+    message.Subject = "My Vacation"
+    message.Body = open("letter.txt", "rb").read()
+    message.attach("picture.jpg")
+
+    sender = mailer.Mailer('mail.example.com')
+    sender.send(message)
+
+"""
+from __future__ import with_statement
+import smtplib
+import socket
+import threading
+import Queue
+import uuid
+
+# this is to support name changes
+# from version 2.4 to version 2.5
+try:
+    from email import encoders
+    from email.header import make_header
+    from email.mime.audio import MIMEAudio
+    from email.mime.base import MIMEBase
+    from email.mime.image import MIMEImage
+    from email.mime.multipart import MIMEMultipart
+    from email.mime.text import MIMEText
+except ImportError:
+    from email import Encoders as encoders
+    from email.Header import make_header
+    from email.MIMEAudio import MIMEAudio
+    from email.MIMEBase import MIMEBase
+    from email.MIMEImage import MIMEImage
+    from email.MIMEMultipart import MIMEMultipart
+    from email.MIMEText import MIMEText
+
+# For guessing MIME type based on file name extension
+import mimetypes
+import time
+
+from os import path
+
+__version__ = "0.8.1"
+__author__ = "Ryan Ginstrom"
+__license__ = "MIT"
+__description__ = "A module to send email simply in Python"
+
+
+class Mailer(object):
+    """
+    Represents an SMTP connection.
+
+    Use login() to log in with a username and password.
+    """
+
+    def __init__(self, host="localhost", port=0, use_tls=False, usr=None, pwd=None, use_ssl=False, use_plain_auth=False,
+                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
+        self.host           = host
+        self.port           = port
+        self.use_tls        = use_tls
+        self.use_ssl        = use_ssl
+        self.use_plain_auth = use_plain_auth
+        self._usr           = usr
+        self._pwd           = pwd
+        self.timeout        = timeout
+
+    def login(self, usr, pwd):
+        self._usr = usr
+        self._pwd = pwd
+
+    def send(self, msg, debug=False):
+        """
+        Send one message or a sequence of messages.
+
+        Every time you call send, the mailer creates a new
+        connection, so if you have several emails to send, pass
+        them as a list:
+        mailer.send([msg1, msg2, msg3])
+        """
+        if self.use_ssl:
+            server = smtplib.SMTP_SSL(self.host, self.port, timeout=self.timeout)
+        else:
+            server = smtplib.SMTP(self.host, self.port, timeout=self.timeout)
+
+        if debug:
+            server.set_debuglevel(1)
+
+        if self._usr and self._pwd:
+            if self.use_tls is True:
+                server.ehlo()
+                server.starttls()
+                server.ehlo()
+
+            if self.use_plain_auth is True:
+                server.esmtp_features["auth"] = "LOGIN PLAIN"
+
+            server.login(self._usr, self._pwd)
+
+        if isinstance(msg, Message):
+            msg = [msg]
+
+        for m in msg:
+            self._send(server, m)
+
+        server.quit()
+
+    def _send(self, server, msg):
+        """
+        Sends a single message using the server
+        we created in send()
+        """
+        me = msg.From
+        if isinstance(msg.To, basestring):
+            to = [msg.To]
+        else:
+            to = list(msg.To)
+
+        cc = []
+        if msg.CC:
+            if isinstance(msg.CC, basestring):
+                cc = [msg.CC]
+            else:
+                cc = list(msg.CC)
+
+        bcc = []
+        if msg.BCC:
+            if isinstance(msg.BCC, basestring):
+                bcc = [msg.BCC]
+            else:
+                bcc = list(msg.BCC)
+
+        rto = []
+        if msg.RTo:
+            if isinstance(msg.RTo, basestring):
+                rto = [msg.RTo]
+            else:
+                rto = list(msg.RTo)
+
+        you = to + cc + bcc
+        server.sendmail(me, you, msg.as_string())
+
+
+class Message(object):
+    """
+    Represents an email message.
+
+    Set the To, From, Reply-To, Subject, and Body attributes as plain-text strings.
+    Optionally, set the Html attribute to send an HTML email, or use the
+    attach() method to attach files.
+
+    Use the charset property to send messages using other than us-ascii
+
+    If you specify an attachments argument, it should be a list of
+    attachment filenames: ["file1.txt", "file2.txt"]
+
+    `To` should be a string for a single address, and a sequence
+    of strings for multiple recipients (castable to list)
+
+    Send using the Mailer class.
+    """
+
+    def __init__(self, **kwargs):
+        """
+        Parameters and default values (parameter names are case insensitive):
+            To=None, From=None, RTo=None, CC=None, BCC=None, Subject=None, Body=None, Html=None,
+            Date=None, Attachments=None, Charset=None, Headers=None
+        """
+
+        # extract  parameters and convert names to lowercase
+        params = {}
+        for i in kwargs:
+            params[i.lower()] = kwargs[i]
+
+        # preprocess attachments
+        self.attachments = []
+        attachments = params.get('attachments', None)
+        if attachments:
+            for attachment in attachments:
+                if isinstance(attachment, basestring):
+                    self.attachments.append((attachment, None, None, None, None))
+                else:
+                    try:
+                        length = len(attachment)
+                    except TypeError:
+                        length = None
+                    else:
+                        if length is None or length <= 4:
+                            self.attachments.append((attachment, None, None, None, None))
+                        else:
+                            self.attachments.append((tuple(attachment) + (None, None, None, None))[:4])
+
+
+        self.To         = params.get('to', None)
+        self.RTo        = params.get('rto', None)
+        self.CC         = params.get('cc', None)
+        self.BCC        = params.get('bcc', None)
+        self.From       = params.get('from', None) # string or iterable
+        self.Subject    = params.get('subject', u'') # string
+        self.Body       = params.get('body', None)
+        self.Html       = params.get('html', None)
+        self.Date       = params.get('date', time.strftime("%a, %d %b %Y %H:%M:%S %z", time.gmtime()))
+        self.charset    = params.get('charset', 'us-ascii')
+        self.Headers    = params.get('headers', {})
+
+        if isinstance(self.Body, unicode):
+            self.Body = self.Body.encode(self.charset)
+
+        self.message_id = self.make_key()
+
+
+    def make_key(self):
+        return str(uuid.uuid4())
+
+    def header(self, key, value):
+        self.Headers[key] = value
+
+    def as_string(self):
+        """Get the email as a string to send in the mailer"""
+
+        if not self.attachments:
+            return self._plaintext()
+        else:
+            return self._multipart()
+
+    def _plaintext(self):
+        """Plain text email with no attachments"""
+
+        if not self.Html:
+            msg = MIMEText(self.Body, 'plain', self.charset)
+        else:
+            msg = self._with_html()
+
+        self._set_info(msg)
+        return msg.as_string()
+
+    def _with_html(self):
+        """There's an html part"""
+
+        outer = MIMEMultipart('alternative')
+
+        part1 = MIMEText(self.Body, 'plain', self.charset)
+        part2 = MIMEText(self.Html, 'html', self.charset)
+
+        outer.attach(part1)
+        outer.attach(part2)
+
+        return outer
+
+    def _set_info(self, msg):
+        if self.charset == 'us-ascii':
+            msg['Subject'] = self.Subject
+            msg['From'] = self.From
+
+        else:
+            if isinstance(self.Subject, unicode):
+                subject = self.Subject
+            else:
+                subject = unicode(self.Subject, self.charset)
+            msg['Subject'] = str(make_header([(subject, self.charset)]))
+
+            if isinstance(self.From, unicode):
+                from_ = self.From
+            else:
+                from_ = unicode(self.From, self.charset)
+            msg['From'] = str(make_header([(from_, self.charset)]))
+
+
+        if isinstance(self.To, basestring):
+            msg['To'] = self.To
+        else:
+            self.To = list(self.To)
+            msg['To'] = ", ".join(self.To)
+
+        if self.RTo:
+            if isinstance(self.RTo, basestring):
+                msg.add_header('reply-to', self.RTo)
+            else:
+                self.RTo = list(self.RTo)
+                msg.add_header('reply-to', ", ".join(self.RTo))
+
+        if self.CC:
+            if isinstance(self.CC, basestring):
+                msg['CC'] = self.CC
+            else:
+                self.CC = list(self.CC)
+                msg['CC'] = ", ".join(self.CC)
+
+
+        if self.BCC:
+            if isinstance(self.BCC, basestring):
+                msg['BCC'] = self.BCC
+            else:
+                self.BCC = list(self.BCC)
+                msg['BCC'] = ", ".join(self.BCC)
+
+
+        if self.Headers:
+            for key, value in self.Headers.items():
+                msg[key] = str(value).encode(self.charset)
+
+
+        msg['Date'] = self.Date
+
+    def _multipart(self):
+        """The email has attachments"""
+
+        msg = MIMEMultipart('related')
+
+        if self.Html:
+            outer = MIMEMultipart('alternative')
+
+            part1 = MIMEText(self.Body, 'plain', self.charset)
+            part1.add_header('Content-Disposition', 'inline')
+
+            part2 = MIMEText(self.Html, 'html', self.charset)
+            part2.add_header('Content-Disposition', 'inline')
+
+            outer.attach(part1)
+            outer.attach(part2)
+            msg.attach(outer)
+        else:
+            msg.attach(MIMEText(self.Body, 'plain', self.charset))
+
+        self._set_info(msg)
+        msg.preamble = self.Subject
+
+        for filename, cid, mimetype, content, charset in self.attachments:
+            self._add_attachment(msg, filename, cid, mimetype, content, charset)
+
+        return msg.as_string()
+
+    def _add_attachment(self, outer, filename, cid, mimetype, content, charset):
+        """
+        If mimetype is None, it will try to guess the mimetype
+        """
+        if mimetype:
+            ctype = mimetype
+            encoding = None
+        else:
+            ctype, encoding = mimetypes.guess_type(filename)
+
+        if ctype is None or encoding is not None:
+            # No guess could be made, or the file is encoded (compressed), so
+            # use a generic bag-of-bits type.
+            ctype = 'application/octet-stream'
+
+        maintype, subtype = ctype.split('/', 1)
+        if not content:
+            with open(filename, 'rb') as fp:
+                content = fp.read()
+
+        if maintype == 'text':
+            # Note: we should handle calculating the charset
+            msg = MIMEText(content, _subtype=subtype, _charset=charset)
+        elif maintype == 'image':
+            msg = MIMEImage(content, _subtype=subtype)
+        elif maintype == 'audio':
+            msg = MIMEAudio(content, _subtype=subtype)
+        else:
+            msg = MIMEBase(maintype, subtype)
+            msg.set_payload(content)
+            # Encode the payload using Base64
+            encoders.encode_base64(msg)
+
+        # Set the content-ID header
+        if cid:
+            msg.add_header('Content-ID', '<%s>' % cid)
+            msg.add_header('Content-Disposition', 'inline')
+        else:
+            # Set the filename parameter
+            msg.add_header('Content-Disposition', 'attachment', filename=path.basename(filename))
+
+        outer.attach(msg)
+
+    def attach(self, filename, cid=None, mimetype=None, content=None, charset=None):
+        """
+        Attach a file to the email. Specify the name of the file;
+        Message will figure out the MIME type and load the file.
+
+        Specify mimetype to set the MIME type manually. The content
+        argument take the contents of the file if they are already loaded
+        in memory.
+        """
+
+        self.attachments.append((filename, cid, mimetype, content, charset))
+
+
+class Manager(threading.Thread):
+    """
+    Manages the sending of email in the background.
+
+    You can supply it with an instance of class Mailer or pass in the same
+    parameters that you would have used to create an instance of Mailer.
+
+    If a message was succesfully sent, self.results[msg.message_id] returns a 3
+    element tuple (True/False, err_code, err_message).
+    """
+
+    def __init__(self, mailer=None, callback=None, **kwargs):
+        threading.Thread.__init__(self)
+
+        self.queue = Queue.Queue()
+        self.mailer = mailer
+        self.abort = False
+        self.callback = callback
+        self._results = {}
+        self._result_lock = threading.RLock()
+
+        if self.mailer is None:
+            self.mailer = Mailer(
+                host=kwargs.get('host', 'localhost'),
+                port=kwargs.get('port', 25),
+                use_tls=kwargs.get('use_tls', False),
+                usr=kwargs.get('usr', None),
+                pwd=kwargs.get('pwd', None),
+            )
+
+    def __getattr__(self, name):
+        if name == 'results':
+            with self._result_lock:
+                return self._results
+        else:
+            return None
+
+    def run(self):
+
+        while self.abort is False:
+            msg = self.queue.get(block=True)
+            if msg is None:
+                break
+
+            if isinstance(msg, Message):
+                msg = [msg]
+
+            for m in msg:
+                try:
+                    self.results[m.message_id] = (False, -1, '')
+                    self.mailer.send(m)
+                    self.results[m.message_id] = (True, 0, '')
+
+                except Exception as e:
+                    args = e.args
+                    if len(args) < 2:
+                        args = (-1, e.args[0])
+
+                    self.results[m.message_id] = (False, args[0], args[1])
+
+                if self.callback:
+                    try:
+                        self.callback(m.message_id)
+                    except Exception:
+                        pass
+
+            # endfor
+
+            self.queue.task_done()
+
+    def send(self, msg):
+        self.queue.put(msg)
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..b14b0bc
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..60030cd
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,28 @@
+from setuptools import setup
+import sys
+
+extra = {}
+if sys.version_info >= (3, 0):
+    extra.update(use_2to3=True)
+
+setup(
+    name='mailer',
+    version="0.8.1",
+    description="A module to send email simply in Python",
+    author="Ryan Ginstrom",
+    author_email='ryan at ginstrom.com',
+    url="https://bitbucket.org/ginstrom/mailer",
+    py_modules=["mailer"],
+    keywords=["email", "smtp"],
+    license="MIT License",
+    classifiers=[
+        'Development Status :: 5 - Production/Stable',
+        'License :: OSI Approved :: MIT License',
+        "Operating System :: MacOS :: MacOS X",
+        "Operating System :: Microsoft :: Windows",
+        "Operating System :: POSIX",
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 3',
+    ],
+    **extra
+)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-mailer.git



More information about the Python-modules-commits mailing list