This is a Python function to send an email (a) with optional text and html alternative parts and (b) via gmail's SMTP server using your gmail account.
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 | def email_it_via_gmail(headers, text=None, html=None, password=None):
"""Send an email -- with text and HTML parts.
@param headers {dict} A mapping with, at least: "To", "Subject" and
"From", header values. "To", "Cc" and "Bcc" values must be *lists*,
if given.
@param text {str} The text email content.
@param html {str} The HTML email content.
@param password {str} Is the 'From' gmail user's password. If not given
it will be prompted for via `getpass.getpass()`.
Derived from http://code.activestate.com/recipes/473810/ and
http://stackoverflow.com/questions/778202/smtplib-and-gmail-python-script-problems
"""
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
import re
import smtplib
import getpass
if text is None and html is None:
raise ValueError("neither `text` nor `html` content was given for "
"sending the email")
if not ("To" in headers and "From" in headers and "Subject" in headers):
raise ValueError("`headers` dict must include at least all of "
"'To', 'From' and 'Subject' keys")
# Create the root message and fill in the from, to, and subject headers
msg_root = MIMEMultipart('related')
for name, value in headers.items():
msg_root[name] = isinstance(value, list) and ', '.join(value) or value
msg_root.preamble = 'This is a multi-part message in MIME format.'
# Encapsulate the plain and HTML versions of the message body in an
# 'alternative' part, so message agents can decide which they want
# to display.
msg_alternative = MIMEMultipart('alternative')
msg_root.attach(msg_alternative)
# Attach HTML and text alternatives.
if text:
msg_text = MIMEText(text.encode('utf-8'), _charset='utf-8')
msg_alternative.attach(msg_text)
if html:
msg_text = MIMEText(html.encode('utf-8'), 'html', _charset='utf-8')
msg_alternative.attach(msg_text)
to_addrs = headers["To"] \
+ headers.get("Cc", []) \
+ headers.get("Bcc", [])
from_addr = msg_root["From"]
# Get username and password.
from_addr_pats = [
re.compile(".*\((.+@.+)\)"), # Joe (joe@example.com)
re.compile(".*<(.+@.+)>"), # Joe <joe@example.com>
]
for pat in from_addr_pats:
m = pat.match(from_addr)
if m:
username = m.group(1)
break
else:
username = from_addr
if not password:
password = getpass.getpass("%s's password: " % username)
smtp = smtplib.SMTP('smtp.gmail.com', 587) # port 465 or 587
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login(username, password)
smtp.sendmail(from_addr, to_addrs, msg_root.as_string())
smtp.close()
|
Nice one. But you forgot to put: import re, to import re module
Thanks. Added.
Should that be
smtp.quit()
instead of.close()
? http://docs.python.org/library/smtplib.html#smtplib.SMTP.quitAdd
_charset='utf-8'
toMIMEText
constructors to fix encoding bug. Thanks Michael.