Welcome, guest | Sign In | My Account | Store | Cart
Python, 136 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env python 
# -*- coding: utf-8 -*-
#
#       gmail.py
#

import sys
import os
import smtplib
import getpass
import ConfigParser
from optparse import OptionParser
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage

'''
Usage: gmail.py [options] arg1

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -f FILE, --file=FILE  image FILE to attach
  -t EMAIL, --to=EMAIL  email destination
  -o NAME, --from=NAME  name of origin
  -b BODY, --body=BODY  BODY message
  -s SUBJECT, --subject=SUBJECT
                        SUBJECT message

Config file example "gmail.cfg"

[Default]
fromaddr = Server email Name
toaddrs  = destination@example.com

[Gmail]
username = MYGMAILUSER
password = MYGMAILPASS

'''
# Program epilog
epilog = \
"""
gmail is configured using a config file only. 
If none is supplied, it will read gmail.cfg 
from current directory or ~/.gmail.cfg.
"""

def main():
    usage = "usage: %prog [options] arg"
    version = "%prog 1.0"
    parser = OptionParser(usage=usage, version=version, epilog=epilog)
    parser.add_option("-f", "--file", dest="image_file",
                  help="image FILE to attach", metavar="FILE")
    parser.add_option("-c", "--conf", dest="config_file",
                  help="config FILE", metavar="CONFIG",
                  default='gmail.cfg')
    parser.add_option("-t", "--to", dest="toaddrs",
                  help="email destination", metavar="EMAIL",
                  default=None)
    parser.add_option("-o", "--from", dest="fromaddr",
                  help="name of origin", metavar="NAME",
                  default=None)
    parser.add_option("-b", "--body", dest="body",
                  help="BODY message", metavar="BODY",
                  default='')
    parser.add_option("-s", "--subject", dest="subject",
                  help="SUBJECT message", metavar="SUBJECT",
                  default='')
    (options, args) = parser.parse_args()
    # Run the program
    process(options, args)

def process(options, args):
    config = get_config(options)
    # Write the email
    msg = MIMEMultipart()
    msg['From'] = config['fromaddr']
    msg['To'] = config['toaddrs']
    msg['Subject'] = options.subject
    body = options.body
    msg.attach(MIMEText(body, 'plain'))
    # Attach image
    if options.image_file:
        try:
            filename = open(options.image_file, "rb")
            attach_image = MIMEImage(filename.read())
            attach_image.add_header('Content-Disposition', 
                                    'attachment; filename = %s'%options.image_file)
            msg.attach(attach_image)
            filename.close()
        except:
            msg.attach(MIMEText('Image attachment error', 'plain'))
    # Converting email to text
    text = msg.as_string()
    
    # The actual mail send
    server = smtplib.SMTP('smtp.gmail.com:587')
    server.ehlo()
    server.starttls()
    server.ehlo()
    server.login(config['username'],config['password'])
    server.sendmail(config['fromaddr'], config['toaddrs'], text)
    server.quit()

def get_config(options):
    conf = {}
    # Read Config File
    config = ConfigParser.RawConfigParser()
    config.read([options.config_file, os.path.expanduser('~/.gmail.cfg')])
    # Gmail Credentials
    try:
        conf['username'] = config.get('Gmail', 'username')
        conf['password'] = config.get('Gmail', 'password')
    except:
        conf['username'] = raw_input('Input Gmail username: ')
        conf['password'] = getpass.getpass('Input Gmail password: ')
    # Email Default
    if options.fromaddr == None:
        try:
            conf['fromaddr'] = config.get('Default', 'fromaddr')
        except:
            conf['fromaddr'] = 'Python Gmail'
    else:
        conf['fromaddr'] = options.fromaddr
    if options.toaddrs == None:
        try:
            conf['toaddrs']  = config.get('Default', 'toaddrs')
        except:
            conf['toaddrs'] = raw_input('Input email destination: ')
    else:
        conf['toaddrs'] = options.toaddrs
    return conf

if __name__ == '__main__':
    main()

4 comments

Mateyuzo 11 years, 5 months ago  # | flag

NIce, tight little script. But couldn't one add server and port arguments and just call it SMTPEmail? Nothing particular to Gmail....

jrovegno (author) 8 years, 10 months ago  # | flag

@Mateyuzo, is a great idea. But there are plenty of better generic scripts for SMTP and I needed to use a straightforward solution for Gmail.

James Holt 7 years, 2 months ago  # | flag

Which version of the email package does this require? I have email 6.0.0a01. It's says it's a test version for email 6. It works for some things, but it doesn't work for this script: it can't find email.MIMEMultipart, etc in email. I like this script because it handles body & attachments, what I have at the moment can do one or the other, but not both in the same email.

James Holt 7 years, 2 months ago  # | flag

On further investigation I found that the version of email I had on my system had a different directory structure the one in the example - the functions appear to be present. All I had to do was alter the code to reflect those differences and I could invoke the required functions.