邮件发送模型及其Python应用实例

SMTP(Simple Mail Transfer Protocol)

制定:

First:RFC 788 in 1981

Last:RFC 5321 in 2008

端口:

TCP 25(SMTP), TCP 465/587(SMTP_SSL)

功能:

用户客户端:

发送消息:SMTP

接收和管理消息:POP3、IMAP

邮件服务器:

发送和接收消息:SMTP

说明:

SMTP仅定义了消息传输格式(如消息发送者参数),而非消息内容(如消息头和消息体)。

邮件发送模型

流程描述:

(1)     使用SMTP协议,通过MUA(Mail User Agent)提交邮件到MSA(Mail Submission Agent),然后MSA递送邮件到MTA(Mail Transfer Agent)[通常而言,MSA和MTA是同一邮件服务器上的两个不同例程,其也被称为SMTP服务器]

(2)    MTA通过DNS在MX(Mail Exchanger Record)上查询接收者的邮件服务器。

(3)    MTA发送邮件到目标邮件服务器MTA,其间可能是两个MTA直接通信,或者经过多个SMTP服务器,最终到达MDA(Mail Delivery Agent)。

(4)    MDA直接递送或者通过SMTP协议,将邮件递送到本地MTA。

(5)    终端应用程序通过IMAP/POP3协议接收和管理邮件。

SMTP协议

SMTP由3部分构成:

  • MAIL:建立发送者地址。
  • RCPT:建立接收者地址。
  • DATA:标志邮件内容的开始。邮件内容由两部分构成:邮件头和以空行分割的邮件体。DATA是一组命令,服务器需要做两次回复:第一次回复表明其准备好接收邮件,第二次回复表明其接收/拒绝整个邮件。

一个简单的SMTP发送示例(主要为了说明SMTP的3个部分),如sender给receiver1和receiver2发送邮件:

S:表示SMTP服务器             C:表示SMTP客户端

客户端C建立TCP连接后,服务端S通过greeting建立会话(附带服务器的FQDN(Fully Qualified Domain Name)),客户端C通过HELLO响应会话(附带客户端的FQDN)。

# 建立会话
S: 220 smtp.example.com ESMTP Postfix
C: HELO client.example.org
S: 250 Hello client.example.org, I am glad to meet you

# 发送消息
C: MAIL FROM:<[email protected]>
S: 250 Ok
C: RCPT TO:<[email protected]>
S: 250 Ok
C: RCPT TO:<[email protected]>
S: 250 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: "Sender Example" <[email protected]>
C: To: "Receiver1 Example" <[email protected]>
C: Cc: [email protected]
C: Date: Tue, 15 January 2008 16:02:43 -0500
C: Subject: Test message
C:
C: Hello Receiver1.
C: This is a test message with 5 header fields and 4 lines in the message body.
C: Your friend,
C: Sender
C: .
S: 250 Ok: queued as 12345
C: QUIT
S: 221 Bye
{The server closes the connection}

Python邮件模块

python中邮件发送使用smtplib模块,其一般流程为:初始化连接->发送邮件->退出。其中包含的类有SMTP,SMTP_SSL,LMTP。如上SMTP中的会话示例在python中对应的部分如下:

C: HELO client.example.org --- SMTP.helo([hostname]): 使用HELO向SMTP服务器标识自己。
S: 250 Hello client.example.org, I am glad to meet you
 --- SMTP.verify(address):服务器用来验证地址的有效性,返回一个元组(250,相关地址)或者(>=400, 错误消息字符串)。
C: MAIL FROM:<[email protected]> --- low-level methods: mail()
C: RCPT TO:<[email protected]> --- low-level methods: rcpt()
C: DATA --- low-level methods: data()
C: QUIT --- SMTP.quit(): 终止会话,关闭连接。

Python Email Demos

  1 # -*- coding:utf-8 -*-
  2 from __future__ import print_function
  3 from __future__ import with_statement
  4
  5
  6 __author__ = ‘xxx‘
  7 __all__ = [‘BTEmail‘]
  8
  9
 10 import smtplib
 11 import sys
 12 import os
 13 import time
 14 import mimetypes
 15 from email import encoders
 16 from email.header import Header
 17 from email.utils import parseaddr, formataddr
 18 from email.mime.text import MIMEText
 19 from email.mime.multipart import MIMEMultipart
 20 from email.mime.image import MIMEImage
 21 from email.mime.audio import MIMEAudio
 22 from email.mime.base import MIMEBase
 23
 24
 25 # ----- The following information should be in the configuration file.
 26 from_addr = ‘[email protected]‘
 27 to_addrs = [‘[email protected]‘,  ‘[email protected]‘]
 28 cc_addrs = [‘[email protected]‘, ‘[email protected]‘]
 29 bcc_addrs = []
 30 username = ‘[email protected]‘
 31 password = ‘---‘
 32 # ------------------------------------------------------------------------------------
 33
 34
 35 class BTEmail(object):
 36     def __init__(self, host=‘smtp.sina.com‘, port=465, username=None, password=None):
 37         self.host = host
 38         self.port = port
 39         self.username = username
 40         self.password = password
 41
 42     @classmethod
 43     def _format_addr(cls, envolope_string):
 44         # parseaddr() only parses single address or string.
 45         (name, addr) = parseaddr(envolope_string)
 46         return formataddr(( 47             Header(name, ‘utf-8‘).encode(), 48             addr.encode(‘utf-8‘) if isinstance(addr, unicode) else addr))
 49
 50     @classmethod
 51     def construct_msg(cls, contentfile, contenttype=‘html‘, charset=‘utf-8‘,                   attach_flag=False, attachpath=None):
 52         with open(contentfile, ‘rb‘) as fp:
 53             content = MIMEText(fp.read(), contenttype, charset)
 54
 55         if not attach_flag:
 56             msg = content
 57         else:
 58             # Construct root container.
 59             msg = MIMEMultipart()
 60             # Attach mail contents to the container.
 61             msg.attach(content)
 62
 63             # Attach attachments to the container.
 64             for filename in os.listdir(attachpath):
 65                 item = os.path.join(attachpath, filename)
 66                 if not os.path.isfile(item):
 67                     continue
 68                 #  Guess the content type based on the file‘s extension.
 69                 (ctype, encoding) = mimetypes.guess_type(item)
 70                 if ctype is None or encoding is not None:
 71                     ctype = ‘application/octet-stream‘
 72                 (maintype, subtype) = ctype.split(‘/‘, 1)
 73
 74                 # Load  and encode attachments.
 75                 """
 76                 # Use MIMEBase class construct attachments.
 77                 with open(item, ‘rb‘) as fp:
 78                     attachment = MIMEBase(_maintype=maintype, _subtype=subtype)
 79                     attachment.set_payload(fp.read())
 80                     encoders.encode_base64(attachment)
 81                 """
 82                 # Use concrete type class construct attachments.
 83                 if maintype == ‘text‘:
 84                     with open(item, ‘rb‘) as fp:
 85                         attachment = MIMEText(fp.read(), _subtype=subtype)
 86                 elif maintype == ‘image‘:
 87                     with open(item, ‘rb‘) as fp:
 88                         attachment = MIMEImage(fp.read(), _subtype=subtype)
 89                 elif maintype == ‘audio‘:
 90                     with open(item, ‘rb‘) as fp:
 91                         attachment = MIMEAudio(fp.read(), _subtype=subtype)
 92                 else:
 93                     with open(item, ‘rb‘) as fp:
 94                         attachment = MIMEBase(_maintype=maintype, _subtype=subtype)
 95                         attachment.set_payload(fp.read())
 96                         encoders.encode_base64(attachment)
 97
 98                 # Set attachment header.
 99                 attachment.add_header(‘Content-Disposition‘, ‘attachment‘, filename=filename)
100                 msg.attach(attachment)
101         return msg
102
103     @classmethod
104     def make_envolope(cls, msg, from_addr, to_addrs, subject=‘A Simple SMTP Demo‘):
105         if msg:
106             msg[‘From‘] = cls._format_addr(u‘BT<%s>‘ % from_addr)
107             # msg[‘To‘] should be a string, not a list.
108             msg[‘To‘] = ‘,‘.join(to_addrs)
109             msg[‘Cc‘] = ‘,‘.join(cc_addrs)
110             msg[‘Bcc‘] = ‘,‘.join(bcc_addrs)
111             msg[‘Subject‘] = Header(u‘主题<%s>‘ % subject, ‘utf-8‘).encode()
112
113     def send_mail(self, from_addr, to_addrs, msg):
114         smtp_server = smtplib.SMTP_SSL()
115         try:
116             #smtp_server.set_debuglevel(True)
117
118             RECONNECT = 10      # Reconnect times.
119             for i in xrange(RECONNECT):
120                 try:
121                     smtp_server.connect(self.host, self.port)
122                 except smtplib.SMTPConnectError:
123                     if i < RECONNECT:
124                         print(‘Connecting to smtp server...‘)
125                         time.sleep(6)
126                         continue
127                     else:
128                         sys.exit(‘Can not connect to smtp server.‘)
129                 except smtplib.SMTPServerDisconnected:
130                     sys.exit(‘SMTP server is lost.‘)
131                 else:
132                     break
133
134             try:
135                 smtp_server.starttls()
136             except smtplib.SMTPException:
137                 print(‘SMTP server does not support the STARTTLS extension.‘)
138
139             try:
140                 smtp_server.login(username, password)
141             except smtplib.SMTPAuthenticationError:
142                 print(‘Username or Password is incorrect.‘)
143
144             try:
145                 refusal_dict = smtp_server.sendmail(from_addr,  to_addrs, msg.as_string())
146             except smtplib.SMTPSenderRefused:
147                 sys.exit(‘SMTP server does not accept the %s.‘ % from_addr)
148             except smtplib.SMTPDataError:
149                 sys.exit(‘SMTP server replied with an unexpected error code .‘)
150             else:
151                 if refusal_dict:
152                     print(‘*****SMTP server rejects the following recipients:*****‘)
153                     print(list(refusal_dict.items()))
154                     print(‘*******************************************************‘)
155         finally:
156             smtp_server.quit()
157
158
159 def main():
160     # Send text/plain email.
161     """
162     email_obj = BTEmail(host=‘smtp.sina.com‘, port=465, username=username, password=password)
163     msg = email_obj.construct_msg(r‘content\mail.txt‘, ‘plain‘, ‘utf-8‘)
164     email_obj.make_envolope(msg, from_addr, to_addrs, subject=‘This is a plain text mail.‘)
165     email_obj.send_mail(from_addr, to_addrs + cc_addrs, msg)
166     """
167
168     # Send text/html email.
169     """
170     email_obj = BTEmail(host=‘smtp.sina.com‘, port=465, username=username, password=password)
171     msg = email_obj.construct_msg(r‘content\mail.html‘, ‘html‘, ‘utf-8‘)
172     email_obj.make_envolope(msg, from_addr, to_addrs, subject=‘This is a html mail.‘)
173     email_obj.send_mail(from_addr, to_addrs + cc_addrs, msg)
174     """
175
176     # Send email with attachments.
177     email_obj = BTEmail(host=‘smtp.sina.com‘, port=465, username=username, password=password)
178     msg = email_obj.construct_msg(r‘content\mail.html‘, ‘html‘, ‘utf-8‘, attach_flag=True, attachpath=r‘attachment‘)
179     email_obj.make_envolope(msg, from_addr, to_addrs, subject=‘A html mail with attachments.‘)
180     email_obj.send_mail(from_addr, to_addrs + cc_addrs, msg)
181
182
183 if __name__ == ‘__main__‘:
184     main()
时间: 2024-10-08 16:23:20

邮件发送模型及其Python应用实例的相关文章

python学习笔记(SMTP邮件发送)

想着给框架添加邮件发送功能.所以整理下python下邮件发送功能 首先python是支持邮件的发送.内置smtp库.支持发送纯文本.HTML及添加附件的邮件 之后是邮箱.像163.qq.新浪等邮箱默认关闭SMTP服务,需要我们手动打开 打开后通过发件人邮箱.授权密码 通过发件人的SMTP服务发送 代码如下: 1 #!/usr/bin/env python 2 # -*- coding: utf_8 -*- 3 4 from email.mime.text import MIMEText 5 fr

.NET开发邮件发送功能的全面教程(含邮件组件源码)

ref: http://www.cnblogs.com/heyuquan/p/net-batch-mail-send-async.html 今天,给大家分享的是如何在.NET平台中开发"邮件发送"功能.在网上搜的到的各种资料一般都介绍的比较简单,那今天我想比较细的整理介绍下: 1)         邮件基础理论知识 2)         邮件发送相关.NET类库 3)         介绍我开发的一个发送邮件的小组件(MailHelper) 4)         MailHelper组

python实现邮件发送完整代码(带附件发送方式)

实例一:利用SMTP与EMAIL实现邮件发送,带附件(完整代码) __author__ = 'Administrator'#coding=gb2312 from email.Header import Headerfrom email.MIMEText import MIMETextfrom email.MIMEMultipart import MIMEMultipartimport smtplib, datetime def SendMailAttach(): msg = MIMEMultip

python学习笔记2:基础(邮件发送)

参考文档:http://www.runoob.com/python/python-email.html SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式. python的smtplib提供了一种很方便的途径发送电子邮件.它对smtp协议进行了简单的封装. Python创建 SMTP 对象语法如下: import smtplib smtpObj = smtplib.SMTP( [host

python学习(二十七)邮件发送及面向对象编程(1)

邮件发送 使用邮件发送功能,需要先做以下三点: 1.在邮箱设置里面打开smtp服务 2.开启邮箱授权码,记住这个授权码 3.安装yagmail,  用 pip install yagmail-0.10.212-py2.py3-none-any.whl,如果直接用 pip install yagmail 中文会有乱码 import yagmail username='[email protected]' passwd='ljia1990312' #授权码 mail=yagmail.SMTP(use

python邮件发送

在基于互联网的应用中,程序经常需要自动地发送电子邮件.如:一个网站的注册系统会在用户注册时发送一封邮件来确认注册:当用户忘记登陆密码的时候,通过邮件来取回密码.smtplib模块是python中smtp(简单邮件传输协议)的客户端实现.我们可以使用smtplib模块,轻松的发送电子邮件.下面的例子用了不到十行代码来发送电子邮件: #coding=gbk import smtplib smtp = smtplib.SMTP() smtp.connect("smtp.yeah.net", 

java mail 邮件发送实例【搬】

说明:转自国外博客:欢迎查阅原作 该实例较新,简明易懂,值得新手借鉴 以gmail为例,注意: 1.通过TLS方式发送 1 package com.mkyong.common; 2 3 import java.util.Properties; 4 5 import javax.mail.Message; 6 import javax.mail.MessagingException; 7 import javax.mail.PasswordAuthentication; 8 import java

Python脚本通过邮件发送zabbix报警图片

Python脚本通过邮件发送zabbix报警图片流程如下: 通过zabbix传递给脚本的message参数,筛选出报警信息的itemid; 通过获取的itemid,在数据库中查找对应的grpahid; 拉取对应graphid的图片并保存; 将报警信息和图片组装成html; 发送邮件. Python脚本如下: #!/usr/bin/python #coding=utf-8 from email.mime.text import MIMEText from email.mime.multipart 

python 邮件发送

#!/usr/bin/env python # -*- coding:UTF-8 -*- #需要在邮箱处设置开启SMTP服务(第三方客户端发送) import smtplibfrom email.mime.text import MIMETextfrom email.utils import formataddrdef mail(): ret = True try: msg = MIMEText('测试邮件','plain','utf-8') msg['From'] = formataddr([