Skip to content

Instantly share code, notes, and snippets.

@SVilgelm
Last active April 21, 2020 00:21
Show Gist options
  • Select an option

  • Save SVilgelm/2620a43bfff10376db7d to your computer and use it in GitHub Desktop.

Select an option

Save SVilgelm/2620a43bfff10376db7d to your computer and use it in GitHub Desktop.

Revisions

  1. SVilgelm revised this gist Jan 21, 2018. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions send_email.py
    Original file line number Diff line number Diff line change
    @@ -32,11 +32,12 @@ def __init__(self, host='', port=0, user=None, password=None,

    def __enter__(self):
    self._smtp = smtplib.SMTP(self.host, self.port)

    if self.password is not None and self.password is not None:
    self._smtp.login(self.user, self.password)
    self._smtp.ehlo()
    if self.use_tls:
    self._smtp.starttls()
    self._smtp.ehlo()
    if self.user is not None and self.password is not None:
    self._smtp.login(self.user, self.password)
    return self

    def __exit__(self, exc_type, exc_val, _exc_tb):
  2. SVilgelm created this gist Sep 12, 2014.
    141 changes: 141 additions & 0 deletions send_email.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,141 @@
    #!/usr/bin/env python2

    from email import header
    from email.mime import audio
    from email.mime import application
    from email.mime import image
    from email.mime import multipart
    from email.mime import text
    import logging
    import mimetypes
    import os
    import re
    import smtplib
    import traceback
    import unittest


    LOG = logging.getLogger(__name__)

    RE_EMAIL = re.compile(r'(?P<name>.+)<(?P<email>.+)>')


    class EmailSender(object):
    def __init__(self, host='', port=0, user=None, password=None,
    use_tls=False):
    self.host = host
    self.port = port
    self.user = user
    self.password = password
    self.use_tls = use_tls
    self._smtp = None

    def __enter__(self):
    self._smtp = smtplib.SMTP(self.host, self.port)

    if self.password is not None and self.password is not None:
    self._smtp.login(self.user, self.password)
    if self.use_tls:
    self._smtp.starttls()
    return self

    def __exit__(self, exc_type, exc_val, _exc_tb):
    if exc_type is not None and exc_val is not None:
    msg = traceback.format_exception_only(exc_type, exc_val)
    LOG.error(msg)
    try:
    self._smtp.quit()
    except smtplib.SMTPException as e:
    LOG.warning(e)
    self._smtp = None

    @staticmethod
    def _files(msg, files):
    for path in files:
    ctype, encoding = mimetypes.guess_type(path)
    if ctype is None or encoding is not None:
    ctype = 'application/octet-stream'
    maintype, subtype = ctype.split('/', 1)

    types = {
    'text': text.MIMEText,
    'image': image.MIMEImage,
    'audio': audio.MIMEAudio
    }

    with open(path, 'rb') as f:
    part = types.get(maintype, application.MIMEApplication)(
    f.read(), _subtype=subtype)

    msg.add_header('Content-Disposition', 'attachment',
    filename=os.path.basename(path))
    msg.attach(part)

    @staticmethod
    def _body(msg, plain=None, html=None):
    for body, subtype in ((plain, 'plain'), (html, 'html')):
    if body:
    part = text.MIMEText(body, _subtype=subtype, _charset='utf-8')
    msg.attach(part)

    @staticmethod
    def _address(address):
    m = RE_EMAIL.match(address)
    if m:
    address = '%s <%s>' % (header.Header(m.group('name'), 'utf-8'),
    m.group('email'))
    return address

    def send(self, me, to, subject=None, plain=None, html=None, files=None):
    if self._smtp is None:
    with self:
    self.send(me, to, subject, plain, html, files)
    return
    if isinstance(to, basestring):
    to = [to]
    msg = multipart.MIMEMultipart()
    msg['From'] = self._address(me)
    msg['To'] = ', '.join(map(self._address, to))
    msg['Subject'] = header.Header(subject or '', 'utf-8')

    self._body(msg, plain, html)
    if files is not None:
    self._files(msg, files)

    self._smtp.sendmail(me, to, msg.as_string())

    __call__ = send


    class TestEmailSender(unittest.TestCase):
    def test_init(self):
    sender = EmailSender()
    self.assertListEqual(['', 0, None, None, False],
    [sender.host, sender.port, sender.user,
    sender.password, sender.use_tls])


    if __name__ == '__main__':
    import argparse
    import sys

    parser = argparse.ArgumentParser(conflict_handler='resolve')
    parser.add_argument('me')
    parser.add_argument('to', nargs='+')
    parser.add_argument('-s', '--subject')
    parser.add_argument('-h', '--host', default='')
    parser.add_argument('-p', '--port', default=0)
    parser.add_argument('-u', '--user')
    parser.add_argument('-w', '--password')
    parser.add_argument('-u', '--use_tls', action='store_true')
    parser.add_argument('-f', '--file', action='append')
    parser.add_argument('-t', '--type', choices=('plain', 'html'),
    default='plain')

    args = parser.parse_args()

    body = sys.stdin.read()
    plain, html = (body, None) if args.type == 'plain' else (None, body)

    EmailSender(args.host, args.port, args.user, args.password, args.use_tls)(
    args.me, args.to, args.subject, plain, html, args.file)