Python SMTP 发送带附件电子邮件

转自:http://blog.csdn.net/zm2714/article/details/7993732


可采用email模块发送电子邮件附件。发送一个未知MIME类型的文件附件其基本思路如下:

1. 构造MIMEMultipart对象做为根容器
2. 构造MIMEText对象做为邮件显示内容并附加到根容器
3. 构造MIMEBase对象做为文件附件内容并附加到根容器
  a. 读入文件内容并格式化
  b. 设置附件头
4. 设置根容器属性
5. 得到格式化后的完整文本
6. 用smtp发送邮件

具体内容参见 14章第6节 “email: Parsing and Composing Mails”。发送一个未知MIME类型的文件附件实例代码如下:

 

[python]  view plain  copy
 
  1. import smtplib  
  2. import email.MIMEMultipart  
  3. import email.MIMEText  
  4. import email.MIMEBase  
  5. import os.path  
  6.   
  7. From = "sender address"  
  8. To = "recipients"  
  9. file_name = "file name"  
  10.   
  11. server = smtplib.SMTP("smtp server address")  
  12. server.login("username","password"#仅smtp服务器需要验证时  
  13.   
  14. # 构造MIMEMultipart对象做为根容器  
  15. main_msg = email.MIMEMultipart.MIMEMultipart()  
  16.   
  17. # 构造MIMEText对象做为邮件显示内容并附加到根容器  
  18. text_msg = email.MIMEText.MIMEText("this is a test text to text mime")  
  19. main_msg.attach(text_msg)  
  20.   
  21. # 构造MIMEBase对象做为文件附件内容并附加到根容器  
  22. contype = 'application/octet-stream'  
  23. maintype, subtype = contype.split('/'1)  
  24.   
  25. ## 读入文件内容并格式化  
  26. data = open(file_name, 'rb')  
  27. file_msg = email.MIMEBase.MIMEBase(maintype, subtype)  
  28. file_msg.set_payload(data.read( ))  
  29. data.close( )  
  30. email.Encoders.encode_base64(file_msg)  
  31.   
  32. ## 设置附件头  
  33. basename = os.path.basename(file_name)  
  34. file_msg.add_header('Content-Disposition',  
  35.  'attachment', filename = basename)  
  36. main_msg.attach(file_msg)  
  37.   
  38. # 设置根容器属性  
  39. main_msg['From'] = From  
  40. main_msg['To'] = To  
  41. main_msg['Subject'] = "attach test "  
  42. main_msg['Date'] = email.Utils.formatdate( )  
  43.   
  44. # 得到格式化后的完整文本  
  45. fullText = main_msg.as_string( )  
  46.   
  47. # 用smtp发送邮件  
  48. try:  
  49.     server.sendmail(From, To, fullText)  
  50. finally:  
  51.     server.quit()  

以上内容转载于:http://www.cnblogs.com/alaska1131/articles/1852653.html

网上关于python的例子所涉及的知识比较烦杂,本着学习Python的心态,掌握发送邮件为知识点,并对代码进行比较分析,对发送邮件相关知识点逐步了解。以下是三段发送邮件代码,均测试成功。


代码一

[python]  view plain  copy
 
  1. # -*- coding: utf-8 -*-  
  2. import smtplib  
  3. import email.MIMEMultipart# import MIMEMultipart  
  4. import email.MIMEText# import MIMEText  
  5. import email.MIMEBase# import MIMEBase  
  6. import os.path  
  7. import mimetypes  
  8. From = "发送邮箱"  
  9. To = "接收箱箱"  
  10. file_name = "c:/1.png"#附件名  
  11.   
  12. server = smtplib.SMTP("smtp.163.com")  
  13. server.login("username","password"#仅smtp服务器需要验证时  
  14.   
  15. # 构造MIMEMultipart对象做为根容器  
  16. main_msg = email.MIMEMultipart.MIMEMultipart()  
  17.   
  18. # 构造MIMEText对象做为邮件显示内容并附加到根容器  
  19. text_msg = email.MIMEText.MIMEText("我this is a test text to text mime",_charset="utf-8")  
  20. main_msg.attach(text_msg)  
  21.   
  22. # 构造MIMEBase对象做为文件附件内容并附加到根容器  
  23.   
  24. ## 读入文件内容并格式化 [方式1]------------------------------  
  25. data = open(file_name, 'rb')  
  26. ctype,encoding = mimetypes.guess_type(file_name)  
  27. if ctype is None or encoding is not None:  
  28.     ctype = 'application/octet-stream'  
  29. maintype,subtype = ctype.split('/',1)  
  30. file_msg = email.MIMEBase.MIMEBase(maintype, subtype)  
  31. file_msg.set_payload(data.read())  
  32. data.close( )  
  33. email.Encoders.encode_base64(file_msg)#把附件编码  
  34. ''''' 
  35.  测试识别文件类型:mimetypes.guess_type(file_name) 
  36.  rar 文件             ctype,encoding值:None None(ini文件、csv文件、apk文件) 
  37.  txt text/plain None 
  38.  py  text/x-python None 
  39.  gif image/gif None 
  40.  png image/x-png None 
  41.  jpg image/pjpeg None 
  42.  pdf application/pdf None 
  43.  doc application/msword None 
  44.  zip application/x-zip-compressed None 
  45.  
  46. encoding值在什么情况下不是None呢?以后有结果补充。 
  47. '''  
  48. #---------------------------------------------  
  49.   
  50. ## 设置附件头  
  51. basename = os.path.basename(file_name)  
  52. file_msg.add_header('Content-Disposition','attachment', filename = basename)#修改邮件头  
  53. main_msg.attach(file_msg)  
  54.   
  55. # 设置根容器属性  
  56. main_msg['From'] = From  
  57. main_msg['To'] = To  
  58. main_msg['Subject'] = "attach test "  
  59. main_msg['Date'] = email.Utils.formatdate( )  
  60.   
  61. # 得到格式化后的完整文本  
  62. fullText = main_msg.as_string( )  
  63.   
  64. # 用smtp发送邮件  
  65. try:  
  66.     server.sendmail(From, To, fullText)  
  67. finally:  
  68.     server.quit()  

代码二

[python]  view plain  copy
 
  1. # -*- coding: utf-8 -*-  
  2. import smtplib  
  3. import email.MIMEMultipart# import MIMEMultipart  
  4. import email.MIMEText# import MIMEText  
  5. import email.MIMEBase# import MIMEBase  
  6. import os.path  
  7.   
  8. From = "发送邮箱"  
  9. To = "接收箱箱"  
  10. file_name = r"c:/1.png"#附件名  
  11.   
  12. server = smtplib.SMTP("smtp.163.com")  
  13. server.login("username","password"#仅smtp服务器需要验证时  
  14.   
  15. # 构造MIMEMultipart对象做为根容器  
  16. main_msg = email.MIMEMultipart.MIMEMultipart()  
  17.   
  18. # 构造MIMEText对象做为邮件显示内容并附加到根容器  
  19. text_msg = email.MIMEText.MIMEText("我this is a test text to text mime",_charset="utf-8")  
  20. main_msg.attach(text_msg)  
  21.   
  22. # 构造MIMEBase对象做为文件附件内容并附加到根容器  
  23. contype = 'application/octet-stream'  
  24. maintype, subtype = contype.split('/'1)  
  25.   
  26. ## 读入文件内容并格式化 [方式2]------------------------------  
  27. data = open(file_name, 'rb')  
  28. file_msg = email.MIMEBase.MIMEBase(maintype, subtype)  
  29. file_msg.set_payload(data.read())  
  30. data.close( )  
  31. email.Encoders.encode_base64(file_msg)#把附件编码  
  32. #---------------------------------------------  
  33. ## 设置附件头  
  34. basename = os.path.basename(file_name)  
  35. file_msg.add_header('Content-Disposition','attachment', filename = basename)#修改邮件头  
  36. main_msg.attach(file_msg)  
  37.   
  38. # 设置根容器属性  
  39. main_msg['From'] = From  
  40. main_msg['To'] = To  
  41. main_msg['Subject'] = "attach test "  
  42. main_msg['Date'] = email.Utils.formatdate( )  
  43.   
  44. # 得到格式化后的完整文本  
  45. fullText = main_msg.as_string( )  
  46.   
  47. # 用smtp发送邮件  
  48. try:  
  49.     server.sendmail(From, To, fullText)  
  50. finally:  
  51.     server.quit()  

代码三

[python]  view plain  copy
 
  1. # -*- coding: utf-8 -*-  
  2. import smtplib  
  3. import email.MIMEMultipart# import MIMEMultipart  
  4. import email.MIMEText# import MIMEText  
  5. import email.MIMEBase# import MIMEBase  
  6. import os.path  
  7.   
  8. import mimetypes  
  9. import email.MIMEImage# import MIMEImage  
  10.   
  11. From = "发送邮箱"  
  12. To = "接收箱箱"  
  13. file_name = "c:/1.png"#附件名  
  14.   
  15. server = smtplib.SMTP("smtp.163.com")  
  16. server.login("username","password"#仅smtp服务器需要验证时  
  17.   
  18. # 构造MIMEMultipart对象做为根容器  
  19. main_msg = email.MIMEMultipart.MIMEMultipart()  
  20.   
  21. # 构造MIMEText对象做为邮件显示内容并附加到根容器  
  22. text_msg = email.MIMEText.MIMEText("我this is a test text to text mime",_charset="utf-8")  
  23. main_msg.attach(text_msg)  
  24.   
  25. # 构造MIMEBase对象做为文件附件内容并附加到根容器  
  26. ctype,encoding = mimetypes.guess_type(file_name)  
  27. if ctype is None or encoding is not None:  
  28.     ctype='application/octet-stream'  
  29. maintype,subtype = ctype.split('/',1)  
  30. file_msg=email.MIMEImage.MIMEImage(open(file_name,'rb').read(),subtype)  
  31. print ctype,encoding  
  32.   
  33. ## 设置附件头  
  34. basename = os.path.basename(file_name)  
  35. file_msg.add_header('Content-Disposition','attachment', filename = basename)#修改邮件头  
  36. main_msg.attach(file_msg)  
  37.   
  38. # 设置根容器属性  
  39. main_msg['From'] = From  
  40. main_msg['To'] = To  
  41. main_msg['Subject'] = "attach test "  
  42. main_msg['Date'] = email.Utils.formatdate( )  
  43.   
  44. # 得到格式化后的完整文本  
  45. fullText = main_msg.as_string( )  
  46.   
  47. # 用smtp发送邮件  
  48. try:  
  49.     server.sendmail(From, To, fullText)  
  50. finally:  
  51.     server.quit()  


相关知识介绍

mailMsg.set_payload(safe_unicode(bodyText).encode(charset), charset=none)

set_payload的参数说明:

参数1:安全二进制流,即文件数据

参数2:编码,默认为none

 详情:http://nullege.com/codes/search/email.MIMEBase.MIMEBase.set_payload

 

知识点汇总:

如果用户A通过B邮箱来向C发送邮件。那么C收到邮件后,如果回复的话,回复的邮件地址是B邮箱。如果想要回复的邮箱是A邮箱,那么就要设置回复邮件的地址,通过python如何设置呢?设置的方法如下:

[python]  view plain  copy
 
  1. main_msg['Reply-to'] = '对方回复的邮箱地址'  

2、对方收到邮件后显示发送邮件方的名称

一般情况下,采用这样的代码:

[python]  view plain  copy
 
  1. main_msg['From'] = '[email protected]'  

对方看到的是该邮箱。如果还想显示用户名,采用如下代码:

[python]  view plain  copy
 
  1. main_msg['From']="大头爸爸<[email protected]>"  

这样,收到邮件的人就会在邮箱收件人一栏中看到:大头爸爸<[email protected]>,而不仅仅显示邮箱的地址。

3、向多人发送邮件

1、一个情况是,如果我向多人发送邮件,但同时我不希望收到邮件的人知道我发给的人。这里就不能设置main_msg['To'],也不能设置main_msg['Cc'](抄送),因为用这两种方式发送,收件人获取邮件时,会列出所有收取该邮件的邮箱。这里只有采用密件的方式发送。即设置main_msg['Bcc']。

2、向多人发送邮件,一定要注意:

[python]  view plain  copy
 
  1. # 用smtp发送邮件  
  2. try:  
  3.     server.sendmail(From, To.split(';'), fullText)  
  4. finally:  
  5.     server.quit()  

sendmail中的那个To是list,不是string,否则只能发给第一个人。因为我传递的多个接收邮件的地址是用半角分号(;)分隔,所以我在这里转为list。

但是设置main_msg['Bcc']时,他的值不能为list,而应该是string。如代码:

[python]  view plain  copy
 
  1. main_msg['Bcc']=To  

经过一翻测试,不设置main_msg['Bcc']值也正常,且符合预期,即收件人在访问邮件时,收件人地址为空。如下图所示:

3、一个奇怪的乱码问题

因为我写的脚本编码保存为utf-8。通过QQ企业邮箱发送给网易邮箱时,邮件内容都很正常,如下图所示:

只是当收到邮件的用户回复时,出现部分内容乱码现象。如下图所示:

python邮件发送代码:

[python]  view plain  copy
 
  1. # -*- coding: utf-8 -*-  
  2. import smtplib  
  3. import email.MIMEMultipart# import MIMEMultipart  
  4. import email.MIMEText# import MIMEText  
  5. import email.MIMEBase# import MIMEBase  
  6. import os.path  
  7. import sys  
  8. import mimetypes  
  9. import email.MIMEImage# import MIMEImage  
  10.   
  11. #命令 mail.py <1:发送方(回复地址)[email protected]> <2:发送地址,多个以;隔开> <3:发送文件>  
  12. From ="合肥顶击科技"  
  13. ReplyTo=sys.argv[1]  
  14. To = sys.argv[2]  
  15. file_name = sys.argv[3]#附件名  
  16.   
  17. server = smtplib.SMTP("smtp.exmail.qq.com",25)  
  18. server.login("[email protected]","xxxxxxx"#仅smtp服务器需要验证时  
  19.   
  20. # 构造MIMEMultipart对象做为根容器  
  21. main_msg = email.MIMEMultipart.MIMEMultipart()  
  22.   
  23. # 构造MIMEText对象做为邮件显示内容并附加到根容器  
  24. text_msg = email.MIMEText.MIMEText("顶击拨号帮你转发的邮件",_charset="utf-8")  
  25. main_msg.attach(text_msg)  
  26.   
  27. # 构造MIMEBase对象做为文件附件内容并附加到根容器  
  28. ctype,encoding = mimetypes.guess_type(file_name)  
  29. if ctype is None or encoding is not None:  
  30.     ctype='application/octet-stream'  
  31. maintype,subtype = ctype.split('/',1)  
  32. file_msg=email.MIMEImage.MIMEImage(open(file_name,'rb').read(),subtype)  
  33.   
  34. ## 设置附件头  
  35. basename = os.path.basename(file_name)  
  36. file_msg.add_header('Content-Disposition','attachment', filename = basename)#修改邮件头  
  37. main_msg.attach(file_msg)  
  38.   
  39. # 设置根容器属性  
  40. main_msg['From'] = From  
  41. main_msg['Reply-to'] = ReplyTo  
  42. #main_msg['To'] = To  
  43. main_msg['Subject'] = "亲,你朋友给你发送的邮件-顶击科技有限公司转发"  
  44. main_msg['Date'] = email.Utils.formatdate()  
  45.   
  46. #main_msg['Bcc'] = To  
  47. # 得到格式化后的完整文本  
  48. fullText = main_msg.as_string( )  
  49.   
  50. # 用smtp发送邮件  
  51. try:  
  52.     server.sendmail(From, To.split(';'), fullText)  
  53. finally:  
  54.     server.quit()  

修改内容如下:

首先,在头部增加:

[python]  view plain  copy
 
  1. from email.header import Header  

1、将“合肥顶击科技”转为utf-8

[python]  view plain  copy
 
  1. From = "%s" % Header("合肥顶击科技","utf-8")  

结果如下:



2、在内容前面加个u

[python]  view plain  copy
 
  1. main_msg['Subject'] = u"亲,你朋友给你发送的邮件-顶击科技有限公司转发"  

或者转为utf-8

[python]  view plain  copy
 
  1. Header("hello,亲,你朋友给你发送的邮件-顶击科技有限公司转发","utf-8")  

现在一切OK,如下图所示:



至此,乱码问题全部解决。上面这个问题是在163邮箱中出现的问题,如果接收邮箱为QQ邮箱,没有发现回复时出现乱码问题。




你可能感兴趣的:(python)