python发邮件小结
2013-03-29
python还是很强大的,同时函数库也多,实现一些功能也很方便,比如现在要讨论的这个发邮件功能。一般而言,电子邮件相关的协议主要是POP3,SMTP等,而python中提供了一个标准库smtplib用来实现简单的邮件收发,废话不多说,直接上干货:
# _*_ coding: utf-8 _*_
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.encoders import encode_base64
import os.path
import os
mailto = ['xxxx@gmail.com']
#mailto用列表可以给多个收件人发,
#但注意在msg['To']里是一个字符串的表达,因此要join成一个字符串
mailhost = 'smtp.163.com'
mailuser = 'xxxx'
mailpawd = 'xxxx'
mailsuffix = '163.com'
def send_mail(to, sub, content, filename):
me = mailuser + '@' + mailsuffix
main_msg = MIMEMultipart()
# construct the plain text part in the mail and attach it
text_msg = MIMEText(content)
main_msg.attach(text_msg)
# construct the attachment part
atttype = 'application/octet-stream'
maintype, subtype = atttype.split('/', 1)
if os.access(filename, os.F_OK): # if file exists
data = open(filename, 'rb')
file_msg = MIMEBase(maintype, subtype) # attachment type
file_msg.set_payload(data.read()) # fill in the file_msg
data.close()
encode_base64(file_msg) # encoding
basename = os.path.basename(filename) # get name without path
file_msg.add_header('Content-Disposition','attachment',
filename = basename)
main_msg.attach(file_msg)
main_msg['Subject'] = sub
main_msg['From'] = me
main_msg['To'] = ', '.join(to)
try:
s =smtplib.SMTP()
s.connect(mailhost)
s.login(mailuser, mailpawd)
s.sendmail(me, to, main_msg.as_string())
s.close()
print 'send success'
except Exception, e:
print str(e)
print 'send failed'
if __name__ == '__main__':
subject = raw_input('enter subject:')
content = raw_input('enter content:')
send_mail(mailto, subject, content,'pic.jpg')
嗯,以上差不多就是这样的功能啦,具体的各种解释代码注释里有,写的时候参照了网上别人的一些文章,过些时候放上链接。
——————————–你以为这么快就结束了的分割线———————————–
嗯,有的朋友们会说:“坑爹呐这是”,确实是略简单了一点。那么换种思路,如果不让使用SMTP协议呢?是不是感觉有点玩人?可是事实就是这样,至少我的环境就是这样,SMTP禁了,不安全。那么又有何办法呢?
好像没有办法了啊。等等,Outlook好像可以发外网啊,那么借助于Outlook是不是能做到同样发邮件的功能呢?
嗯,google没有负我,搜出来确实有方法可以解决,不过需要借助第三方函数库win32com,这个是pythonwin中自带的对win32 中COM组件的API的一层封装,刚想找一个定义,无奈google被墙,baidu搜出来的结果惨不忍睹,只好作罢。以后看情况补上。按我的理解就是根 据COM的调用方式提供在python中的实现,一般而言,需要对已有的COM组件扫描进行makepy操作然后才方便进行COM组件的调用。然后在 win32com.client.constants.*使用该COM定义的各种常量参数等。
具体的情况还是如以下代码来呈现吧:
# -*- coding:utf-8 -*-
#========================================================
# This file mainly handler the mail sent function.
# Attention, you need install win32com to drive, or it will crash.
# Moreover, the Outlook security level must be lower.
# In Tools->Trust Center->Programmatic Access->Never warn me ... Check it.
# may other issues comes up out of my consideration. just feel free to
# contact me. mail to qwop369258@gmail.com
#========================================================
import win32com.client
import time
attachmentlist = [r'D:pic.jpg', r'D:pic2.jpg']
recvlist = ['xxxxx@sap.com','xxxxxx@gmail.com']
def sendmail(recvlist, attachmentlist, subject, content, iswithtime):
s = win32com.client.Dispatch("Outlook.Application")
ol = s.GetNamespace('MAPI')
# test if outlook can be connected
inbox = ol.GetDefaultFolder(win32com.client.constants.olFolderInbox)
messages = inbox.Items
# print 'numbers: %s' % messages.Count
# somemail = messages.Item()
# f = open('cc.html','w')
# f.write(somemail.HTMLBody)
# f.close()
mail = s.CreateItem(win32com.client.constants.olMailItem)
# Add recipients
for recv in recvlist:
mail.Recipients.Add(recv)
# Add attachments
for attachment in attachmentlist:
mail.Attachments.Add(attachment)
# Time stamp preparation
now = time.localtime()
str_date = time.strftime('%m/%d/%Y', now)
str_time = time.strftime('%X', now)
# Compose mail subject and content
mail.Subject = subject
if iswithtime:
mail.Subject = mail.Subject + ' in ' + str_date
mail.Body = content
if iswithtime:
mail.Body = mail.Body + 'rngenerated at ' + str_date + ' ' + str_time
mail.Send()
if __name__ == '__main__':
sendmail(recvlist, attachmentlist, 'test7', 'test', False)
主要还是以下的格式:
x = win32com.client.Dispatch("some COM")
x.property = yyyyy
x.method(args)
python很简单,这个功能又简单,应该看一下就知道意思了,也不详细说了,不懂的可以留言问我
需要注意的一点是,在调用Outlook时会有一个安全性问题,就是外部调用它的API发邮件会有警告,还是要手动点allow或者deny,有一个方法可以去除掉相关的警告,在第二段代码开头注释有相关的操作说明。
再次,第二种方法感觉并不优雅,不知道有什么更好的方法可以实现功能,还请围观群众不吝赐教。