基于smtplib包制作而成,但在实践中发现一个不知道算不算是smtplib留的一个坑,在网络断开的情况下发送邮件时会抛出一个socket.gaierror的异常,但是smtplib中并没有捕获这个异常,导致程序会因这个异常终止,因此代码中针对这部分的异常进行处理,确保不会异常终止。 #!/usr/bin/env python

# -*- coding: utf-8 -*-

__author__ = 'Zoa Chou'

# see http://www.mudoom.com/Article/show/id/29.html for detail

import logging

import smtplib

import mimetypes

import socket

from email import encoders

from email.header import Header

from email.mime.text import MIMEText, MIMENonMultipart

from email.mime.base import MIMEBase

from email.utils import parseaddr, formataddr

class Mailer(object):

def __init__(self):

pass

def send_mail(self, smtp_server, from_address, to_address, subject, body, files=None):

"""

发送邮件主程序

:param smtp_server: dict 邮件服务器设置

:keyword host: string smtp服务器地址

:keyword port: int smtp服务器端口号

:keyword user: string 用户名

:keyword passwd: string 密码

:keyword ssl: bool 是否启用ssl,默认False

:keyword timeout: int 超时时间,默认10s

:param from_address: 发件人邮箱

:param to_address: 收件人邮箱

:param subject: 邮件标题

:param body: 邮件内容

:param files: 附件

:raise: NetworkError/MailerException

"""

# 格式化邮件内容

body = self._encode_utf8(body)

# 邮件类型

content_type = 'html' if body.startswith('') else 'plain'

msg = MIMENonMultipart() if files else MIMEText(body, content_type, 'utf-8')

# 格式化邮件数据

msg['From'] = self._format_address(from_address)

msg['To'] = ', '.join(self._format_list(to_address))

msg['subject'] = self._encode_utf8(subject)

# 构造附件数据

if files:

msg.attach(MIMEText(body, content_type, 'utf-8'))

cid = 0

for file_name, payload in files:

file_name = self._encode_utf8(file_name)

main_type, sub_type = self._get_file_type(file_name)

if hasattr(payload, 'read'):

payload = payload.read()

f_name = self._encode_header(file_name)

mime = MIMEBase(main_type, sub_type, filename=f_name)

mime.add_header('Content-Disposition', 'attachment', filename=f_name)

mime.add_header('Content-ID', '' % cid)

mime.add_header('X-Attachment-Id', '%s' % cid)

mime.set_payload(payload)

encoders.encode_base64(mime)

msg.attach(mime)

cid += 1

host = smtp_server.get('host')

port = smtp_server.get('port')

user = smtp_server.get('user')

passwd = smtp_server.get('passwd')

ssl = smtp_server.get('ssl', False)

time_out = smtp_server.get('timeout', 10)

# 没有输入端口则使用默认端口

if port is None or port == 0:

if ssl:

port = 465

else:

port = 25

logging.debug('Send mail form %s to %s' % (msg['From'], msg['To']))

try:

if ssl:

# 开启ssl连接模式

server = smtplib.SMTP_SSL('%s:%d' % (host, port), timeout=time_out)

else:

server = smtplib.SMTP('%s:%d' % (host, port), timeout=time_out)

# 开启调试模式

# server.set_debuglevel(1)

# 如果存在用户名密码则尝试登录

if user and passwd:

server.login(user, passwd)

# 发送邮件

server.sendmail(from_address, to_address, msg.as_string())

logging.debug('Mail sent success.')

# 关闭stmp连接

server.quit()

except socket.gaierror, e:

""" 网络无法连接 """

logging.exception(e)

raise NetworkError(e)

except smtplib.SMTPServerDisconnected, e:

""" 网络连接异常 """

logging.exception(e)

raise NetworkError(e)

except smtplib.SMTPException, e:

""" 邮件发送异常 """

logging.exception(e)

raise MailerException(e)

def _format_address(self, s):

"""

格式化邮件地址

:param s:string 邮件地址

:return: string 格式化后的邮件地址

"""

name, address = parseaddr(s)

return formataddr((self._encode_header(name), self._encode_utf8(address)))

def _encode_header(self, s):

"""

格式化符合MIME的头部数据

:param s: string 待格式化数据

:return: 格式化后的数据

"""

return Header(s, 'utf-8').encode()

def _encode_utf8(self, s):

"""

格式化成utf-8编码

:param s: string 待格式化数据

:return: string 格式化后的数据

"""

if isinstance(s, unicode):

return s.encode('utf-8')

else:

return s

def _get_file_type(self, file_name):

"""

获取附件类型

:param file_name: 附件文件名

:return: dict 附件MIME

"""

s = file_name.lower()

pos = s.rfind('.')

if pos == -1:

return 'application', 'octet-stream'

ext = s[pos:]

mime = mimetypes.types_map.get(ext, 'application/octet-stream')

pos = mime.find('/')

if pos == (-1):

return mime, ''

return mime[:pos], mime[pos+1:]

def _format_list(self, address):

"""

将收件人地址格式化成list

:param address: string/list 收件人邮箱

:return: list 收件人邮箱list

"""

l = address

if isinstance(l, basestring):

l = [l]

return [self._format_address(s) for s in l]

class MailerException(Exception):

""" 邮件发送异常类 """

pass

class NetworkError(MailerException):

""" 网络异常类 """

pass

# test for @qq.com

if __name__ == '__main__':

import sys

def prompt(prompt):

"""

接收终端输入的数据

"""

sys.stdout.write(prompt + ": ")

return sys.stdin.readline().strip()

from_address = prompt("From(Only @qq.com)")

passwd = prompt("Password")

to_address = prompt("To").split(',')

subject = prompt("Subject")

print "Enter message, end with ^D:"

msg = ''

while 1:

line = sys.stdin.readline()

if not line:

break

msg = msg + line

print "Message length is %d" % len(msg)

# QQ邮箱默认设置

smtp_server = {'host': 'smtp.qq.com', 'port': None, 'user': from_address, 'passwd': passwd, 'ssl': True}

mailer = Mailer()

try:

mailer.send_mail(smtp_server, from_address, to_address, subject, msg)

except MailerException, e:

print(e)

以上所述就是本文的全部内容了,希望大家能够喜欢。

smtplib python教程_Python基于smtplib实现异步发送邮件服务相关推荐

  1. smtplib python教程_python使用smtplib模块发送邮件

    使用smtplib模块发送邮件,供大家参考,具体内容如下 1)使用smtplib模块发送简单邮件 步骤: 1.连接SMTP服务器,并使用用户名.密码登陆服务器 2.创建EmailMessage对象,该 ...

  2. smtplib python教程_Python smtplib 教程

    Python smtplib 教程展示了如何使用 smtplib 模块在 Python 中发送电子邮件. 要发送电子邮件,我们使用 Python 开发服务器,Mailtrap 在线服务和共享的网络托管 ...

  3. smtplib python教程_Python使用poplib模块和smtplib模块收发电子邮件的教程

    poplib模块接收邮件python的poplib模块是用来从pop3收取邮件的,也可以说它是处理邮件的第一步. POP3协议并不复杂,它也是采用的一问一答式的方式,你向服务器发送一个命令,服务器必然 ...

  4. smtplib python教程_Python模块入门教程之smtplib 邮件发送

    Python的smtplib提供了一种很方便的途径发送电子邮件.它对smtp协议进行了简单的封装. smtp协议的基本命令包括: HELO 向服务器标识用户身份 MAIL 初始化邮件传输 mail f ...

  5. python画代码-Python教程_Python画Mandelbrot集 代码

    Python教程_Python画Mandelbrot集 代码 作者:Comet 来源: 课课家 www.kokojia.com点击数:278发布时间:2015-06-19 11:17:19 曼德勃罗集 ...

  6. python异步框架twisted_twisted是python实现的基于事件驱动的异步网络通信构架。

    网:https://twistedmatrix.com/trac/ http://www.cnblogs.com/wy-wangyan/p/5252271.html What is Twisted? ...

  7. 手机python教程_python教程下载

    python教程是一款非常实用的python编程学习软件平台,这里有着超多实用python课程,帮助小白学习python编程,了解各种函数以及代码运用,这里的课程非常完善,覆盖了基础框架,函数设计,文 ...

  8. Python教程三:使用Flask搭建web服务

    教程二:使用Aestate操作数据库 Python教程二:使用Aestate操作数据库_Cx_轩的博客-CSDN博客​​​​​​ ----------------------------------- ...

  9. python图像处理教程_Python基于Tensor FLow的图像处理操作详解

    本文实例讲述了Python基于Tensor FLow的图像处理操作.分享给大家供大家参考,具体如下: 在对图像进行深度学习时,有时可能图片的数量不足,或者希望网络进行更多的学习,这时可以对现有的图片数 ...

最新文章

  1. 面试官问:请拿出一段体现你水平的代码,我该如何回答?
  2. Activiti 开始流程时存储发起人员USERID
  3. 欧洲估值最高的5家人工智能创业公司
  4. STM32 基础系列教程 27 - USB_HID
  5. 人们常说的微型计算机简称为 机,(精华版)国家开放大学电大专科《计算机文化基础》网络课单项选择题题库及答案...
  6. LeetCode 623. 在二叉树中增加一行(BFS/DFS)
  7. 机器学习系统:设计与实现 计算图
  8. 【XSY2519】神经元 prufer序列 DP
  9. 热敏电阻如何查表计算温度_额温枪温补算法:热电堆温度补偿算法 MTP10B7F55
  10. NIOS II EDS NIOS II IDE 转载
  11. 如何用hypermesh生成包含interface的流体网格
  12. 关于mac的open命令
  13. 产品经理笔试面试(题目+答案)
  14. 阿里云发生故障,网友炸了,官方回应道歉。对此事你怎么看?
  15. ESP8266/ESP32 +1.3“ or 0.96“ IIC OLED指针式时钟
  16. 门面模式、调停者模式、责任链模式
  17. 微信小程序中音频播放
  18. leetcode-回溯
  19. 微信小程序开发之——用户登录-搭建开发者服务器(2)
  20. 分体式降噪耳机有哪些?高配置分体式降噪耳机排行榜

热门文章

  1. AspNetForums 开发过程中的源代码管理
  2. Ubuntu下LDAP 部署文档
  3. 避免服务器成为肉鸡的应对措施
  4. ELK官方文档:在Kibana加密通讯
  5. VBA中的数据字典,可以理解为Java中的Map
  6. 加菲猫的人生歪理~ 看完果然开心,哈哈~
  7. 成功要掌握人生的每一次机会
  8. 移动端页面兼容性问题解决方案整理(一)
  9. Ubuntu登录异常: 输入正确的密码, 但是却无法进入系统, 总是返回到登录界面, 但是用ctrl+alt+F1-F文字界面登录都可以进入。
  10. Xshell连接mysql数据库乱码问题解决思路总结