| 1 | """ |
|---|
| 2 | Helper library to ease emailing. |
|---|
| 3 | """ |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | import smtplib |
|---|
| 8 | import email |
|---|
| 9 | from email import Encoders |
|---|
| 10 | from email.Utils import formatdate |
|---|
| 11 | from email.Message import Message |
|---|
| 12 | from email.MIMEAudio import MIMEAudio |
|---|
| 13 | from email.MIMEBase import MIMEBase |
|---|
| 14 | from email.MIMEMultipart import MIMEMultipart |
|---|
| 15 | from email.MIMEImage import MIMEImage |
|---|
| 16 | from email.MIMEText import MIMEText |
|---|
| 17 | import mimetypes |
|---|
| 18 | |
|---|
| 19 | FROMEMAIL = 'ryan@acceleration.net' |
|---|
| 20 | SERVER = 'mail.acceleration.net' |
|---|
| 21 | |
|---|
| 22 | def rawEmail(toList, msg, server=SERVER, fromEmail=FROMEMAIL): |
|---|
| 23 | |
|---|
| 24 | s = smtplib.SMTP(server) |
|---|
| 25 | smtpresult = s.sendmail(fromEmail, toList, msg) |
|---|
| 26 | |
|---|
| 27 | if smtpresult: |
|---|
| 28 | errstr = "" |
|---|
| 29 | for recip in smtpresult.keys(): |
|---|
| 30 | errstr = """Could not delivery mail to: %s |
|---|
| 31 | |
|---|
| 32 | Server said: %s |
|---|
| 33 | %s |
|---|
| 34 | |
|---|
| 35 | %s""" % (recip, smtpresult[recip][0], smtpresult[recip][1], errstr) |
|---|
| 36 | raise smtplib.SMTPException, errstr |
|---|
| 37 | |
|---|
| 38 | |
|---|
| 39 | def processTo(to): |
|---|
| 40 | """ |
|---|
| 41 | helper function that processes a string or list of addresses. |
|---|
| 42 | |
|---|
| 43 | returns (list of addresses, comma-delimited string of addresses) |
|---|
| 44 | |
|---|
| 45 | The first is used for rawEmail, and the second is used when creating |
|---|
| 46 | headers. |
|---|
| 47 | """ |
|---|
| 48 | toList = [] |
|---|
| 49 | if type(to) is list: |
|---|
| 50 | toList = to[:] |
|---|
| 51 | to = ", ".join(to) |
|---|
| 52 | else: |
|---|
| 53 | toList = [to] |
|---|
| 54 | |
|---|
| 55 | return (toList, to) |
|---|
| 56 | |
|---|
| 57 | def mail(to, subject, message, html=False, fromEmail=FROMEMAIL, server=SERVER): |
|---|
| 58 | """ |
|---|
| 59 | Simplifies the emailing process, sending plaintext emails. |
|---|
| 60 | |
|---|
| 61 | to: accepts a list of emails or a single email. |
|---|
| 62 | |
|---|
| 63 | returns nothing, or throws an smtplib.SMTPException if there is a problem. |
|---|
| 64 | """ |
|---|
| 65 | toList, to = processTo(to) |
|---|
| 66 | |
|---|
| 67 | htmlHeader = '\n' |
|---|
| 68 | |
|---|
| 69 | if html: |
|---|
| 70 | htmlHeader = 'Content-Type: text/html; charset=ISO-8859-1\n\n' |
|---|
| 71 | |
|---|
| 72 | msg = '''To: %s |
|---|
| 73 | From: %s |
|---|
| 74 | Subject: %s |
|---|
| 75 | Date: %s |
|---|
| 76 | %s |
|---|
| 77 | %s |
|---|
| 78 | ''' % (to, fromEmail, subject, formatdate(), htmlHeader, message) |
|---|
| 79 | |
|---|
| 80 | rawEmail(toList, msg, fromEmail=fromEmail, server=server) |
|---|
| 81 | |
|---|
| 82 | |
|---|
| 83 | def sms_me(subject, message): |
|---|
| 84 | " sends an email to ryan's phone " |
|---|
| 85 | mail('sms-ryan@acceleration.net', subject, message) |
|---|
| 86 | |
|---|
| 87 | def emailHtml(to, subject, message): |
|---|
| 88 | toList, to = processTo(to) |
|---|
| 89 | msg = MIMEMultipart() |
|---|
| 90 | msg['Subject'] = subject |
|---|
| 91 | msg['To'] = to |
|---|
| 92 | msg['From'] = fromEmail |
|---|
| 93 | msg['Date'] = formatdate() |
|---|
| 94 | msg.preamble = 'You are not using a MIME-aware reader\n' |
|---|
| 95 | msg.epilogue = '' |
|---|
| 96 | |
|---|
| 97 | #add the main message |
|---|
| 98 | msg.attach(MIMEText(message)) |
|---|
| 99 | |
|---|
| 100 | rawEmail(toList, msg.as_string()) |
|---|
| 101 | |
|---|
| 102 | def emailFile(to, subject, message, filePath, mimeType=None, fromEmail=FROMEMAIL, server=SERVER): |
|---|
| 103 | """ |
|---|
| 104 | sends an email attachment to the given address or list of addesses. |
|---|
| 105 | |
|---|
| 106 | if the mimeType is not specified, it uses mimetypes.guess_type to determine it. |
|---|
| 107 | """ |
|---|
| 108 | toList, to = processTo(to) |
|---|
| 109 | |
|---|
| 110 | msg = MIMEMultipart() |
|---|
| 111 | msg['Subject'] = subject |
|---|
| 112 | msg['To'] = to |
|---|
| 113 | msg['From'] = fromEmail |
|---|
| 114 | msg['Date'] = formatdate() |
|---|
| 115 | msg.preamble = 'You are not using a MIME-aware reader\n' |
|---|
| 116 | msg.epilogue = '' |
|---|
| 117 | |
|---|
| 118 | #add the main message |
|---|
| 119 | msg.attach(MIMEText(message)) |
|---|
| 120 | |
|---|
| 121 | if type(filePath) is list: |
|---|
| 122 | for f in filePath: |
|---|
| 123 | addFile(f, msg, mimeType) |
|---|
| 124 | else: |
|---|
| 125 | addFile(filePath, msg, mimeType) |
|---|
| 126 | |
|---|
| 127 | rawEmail(toList, msg.as_string(), server=server, fromEmail=fromEmail) |
|---|
| 128 | |
|---|
| 129 | def addFile(filePath, message, mimeType=None): |
|---|
| 130 | if mimeType is None: |
|---|
| 131 | mimeType = mimetypes.guess_type(filePath)[0] |
|---|
| 132 | |
|---|
| 133 | maintype, subtype = mimeType.split('/', 1) |
|---|
| 134 | |
|---|
| 135 | def processFactory(mimeRunner, openMethod): |
|---|
| 136 | def proc(path, subtype): |
|---|
| 137 | fp = open(path, openMethod) |
|---|
| 138 | fileMsg = mimeRunner(fp.read(), _subtype = subtype) |
|---|
| 139 | fp.close() |
|---|
| 140 | return fileMsg |
|---|
| 141 | |
|---|
| 142 | return proc |
|---|
| 143 | |
|---|
| 144 | messageMaker = {'text':processFactory(MIMEText, 'r'), |
|---|
| 145 | 'image':processFactory(MIMEImage, 'rb'), |
|---|
| 146 | 'audio':processFactory(MIMEAudio, 'rb')} |
|---|
| 147 | |
|---|
| 148 | |
|---|
| 149 | |
|---|
| 150 | fMsg = None |
|---|
| 151 | if messageMaker.has_key(maintype): |
|---|
| 152 | fMsg = messageMaker[maintype](filePath, subtype) |
|---|
| 153 | else: |
|---|
| 154 | fp = open(filePath, 'rb') |
|---|
| 155 | fMsg = MIMEBase(maintype, subtype) |
|---|
| 156 | fMsg.set_payload(fp.read()) |
|---|
| 157 | fp.close() |
|---|
| 158 | # Encode the payload using Base64 |
|---|
| 159 | Encoders.encode_base64(fMsg) |
|---|
| 160 | |
|---|
| 161 | if fMsg is not None: |
|---|
| 162 | fMsg.add_header('Content-Disposition', 'attachment', filename=filePath) |
|---|
| 163 | message.attach(fMsg) |
|---|
| 164 | |
|---|