邮件发送/接收

简单的文本邮件

代码1

 1 #不知道为啥这个代码有时候发送成功,有时候发送不成功,简略的测试了一下大概10次中能成功4次
 2 #!/usr/bin/python
 3 
 4 import smtplib
 5 from email.mime.text import MIMEText
 6 from email.header import Header
 7 
 8 pwd_file = open('163mail.txt', 'r')
 9 sender_file = open('senders.txt', 'r')
10 receiver_file = open('receivers.txt', 'r')
11 
12 pwd = pwd_file.read()
13 sender = sender_file.read()
14 receiver = receiver_file.read()
15 
16 pwd_file.close()
17 sender_file.close()
18 receiver_file.close()
19 
20 message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
21 message['From'] = sender
22 message['To'] = receiver
23 
24 subject = 'Python SMTP 邮件测试'
25 message['Subject'] = Header(subject, 'utf-8')
26 
27 try:
28     smtpObj = smtplib.SMTP_SSL('smtp.163.com', 465)
29     smtpObj.login(sender, pwd)
30     smtpObj.sendmail(sender, receiver, message.as_string())
31     print('邮件发送成功')
32 except smtplib.SMTPException as e:
33     print('Error: 无法发送邮件.Case:%s' % e)
View Code

代码2

 1 #!/usr/bin/python3
 2 
 3 import smtplib
 4 import email.mime.multipart
 5 import email.mime.text
 6 
 7 pwd_file = open('163mail.txt', 'r')
 8 sender_file = open('senders.txt', 'r')
 9 receiver_file = open('receivers.txt', 'r')
10 
11 pwd = pwd_file.read()
12 sender = sender_file.read()
13 receiver = receiver_file.read()
14 
15 pwd_file.close()
16 sender_file.close()
17 receiver_file.close()
18 
19 Subject = 'Subject'
20 From = 'From'
21 To = 'To'
22 
23 msg = email.mime.multipart.MIMEMultipart()  
24 
25 msg[Subject] = 'happy' #非常奇怪的是这里有些字符串不能用,如hello, he,hi等
26 msg[From] = sender
27 msg[To] = receiver
28 
29 #邮件正文
30 content = '''
31     hello world!
32 '''
33 
34 txt = email.mime.text.MIMEText(content)
35 msg.attach(txt)
36 
37 try:
38     smtp = smtplib.SMTP()
39     smtp.connect('smtp.163.com', '25')
40     smtp.login(sender, pwd)
41     smtp.sendmail(sender, receiver, msg.as_string())
42     smtp.quit()
43     print('email sent successfully!')
44 except smtplib.SMTPException as e:
45     print('email failed!
%s' % e)
View Code

发送 html 格式的邮件

如果要发送 html 邮件而非纯文本文件,将上面的代码1稍微修改一下即可:

在构造 MIMEText 对象时把 html 字符串传进去,再把第二个参数由 plain 变为 html 即可

代码:

 1 #!/usr/bin/python
 2 
 3 import smtplib
 4 from email.mime.text import MIMEText
 5 from email.header import Header
 6 
 7 pwd_file = open('163mail.txt', 'r')
 8 sender_file = open('senders.txt', 'r')
 9 receiver_file = open('receivers.txt', 'r')
10 
11 pwd = pwd_file.read()
12 sender = sender_file.read()
13 receiver = receiver_file.read()
14 
15 pwd_file.close()
16 sender_file.close()
17 receiver_file.close()
18 
19 mail_msg = '''
20 <p>python 邮件发送测试</p>
21 <p><a href = "http://www.runoob.com">这是一个链接</a></p>
22 '''
23 
24 message = MIMEText(mail_msg, 'html', 'utf-8')
25 message['From'] = sender
26 message['To'] = receiver
27 
28 subject = 'Python SMTP 邮件测试'
29 message['Subject'] = Header(subject, 'utf-8')
30 
31 try:
32     smtpObj = smtplib.SMTP_SSL('smtp.163.com', 465)
33     smtpObj.login(sender, pwd)
34     smtpObj.sendmail(sender, receiver, message.as_string())
35     print('邮件发送成功')
36 except smtplib.SMTPException as e:
37     print('Error: 无法发送邮件.Case:%s' % e)
View Code

发送带附件的邮件

带附件的邮件可以看作包含文本和各个附件,可以构建一个 MIMEMultipart 对象代表邮件本身,然后往里面添加一个 MIMEText 作为邮件正文,再添加表示附件的 MIMEBase 对象即可

代码:

 1 #!/usr/bin/python
 2 
 3 import smtplib
 4 from email.mime.text import MIMEText
 5 from email.mime.multipart import MIMEMultipart
 6 from email.header import Header
 7 
 8 pwd_file = open('163mail.txt', 'r')
 9 sender_file = open('senders.txt', 'r')
10 receiver_file = open('receivers.txt', 'r')
11 
12 pwd = pwd_file.read()
13 sender = sender_file.read()
14 receiver = receiver_file.read()
15 
16 pwd_file.close()
17 sender_file.close()
18 receiver_file.close()
19 
20 message = MIMEMultipart() #创建一个带附件的实例
21 message['From'] = sender
22 message['To'] = receiver
23 subject = 'Python SMTP 邮件测试'
24 message['Subject'] = Header(subject, 'utf-8')
25 
26 #邮件正文
27 content = '''
28 # this is a python mail test.
29 '''
30 message.attach(MIMEText(content, 'plain', 'utf-8'))
31 
32 #构造附件1,传送当前目录下的 test.txt 文件
33 att1 = MIMEText(open('test.txt', 'rb').read(), 'base64', 'utf-8')
34 att1['Content-Type'] = 'application/octed-stream'
35 # 这里的filename可以任意些,写什么名字,邮件中就显示什么名字
36 att1['Content-Disposition'] = 'attachment;filename="test.txt"'
37 message.attach(att1)
38 
39 #构造附件2,发送 HELLO.ASM 文件
40 att2 = MIMEText(open('D://Project/HELLO.ASM', 'rb').read(), 'base64', 'utf-8')
41 att2['Content-Type'] = 'application/octed-stream'
42 att2['Content-Disposition'] = 'attachment;filename="HELLO.ASM"'
43 message.attach(att2)
44 
45 #依此类推可以构造附件 3, 4, 5...
46 
47 try:
48     smtp = smtplib.SMTP()
49     smtp.connect('smtp.163.com', '25')
50     smtp.login(sender, pwd)
51     smtp.sendmail(sender, receiver, message.as_string())
52     smtp.quit()
53     print('email sent successfully!')
54 except smtplib.SMTPException as e:
55     print('email failed!
%s' % e)
56 
57 # try:
58 #     smtpObj = smtplib.SMTP_SSL('smtp.163.com', 465)
59 #     smtpObj.login(sender, pwd)
60 #     smtpObj.sendmail(sender, receiver, message.as_string())
61 #     print('邮件发送成功')
62 # except smtplib.SMTPException as e:
63 #     print('Error: 无法发送邮件.Case:%s' % e)
View Code

发送图片

代码:

 1 #!/usr/bin/python3
 2 
 3 import smtplib
 4 import email.mime.multipart
 5 import email.mime.text
 6 import email.mime.image
 7 
 8 pwd_file = open('163mail.txt', 'r')
 9 sender_file = open('senders.txt', 'r')
10 receiver_file = open('receivers.txt', 'r')
11 
12 pwd = pwd_file.read()
13 sender = sender_file.read()
14 receiver = receiver_file.read()
15 
16 pwd_file.close()
17 sender_file.close()
18 receiver_file.close()
19 
20 Subject = 'Subject'
21 From = 'From'
22 To = 'To'
23 
24 msg = email.mime.multipart.MIMEMultipart('related')#设置为多文本格式
25 
26 msg[Subject] = 'happy' #非常奇怪的是这里有些字符串不能用,如hello, he,hi等
27 msg[From] = sender
28 msg[To] = receiver
29 
30 #不能直接将图片和文本一起放到一个MIMEMultipart对象中,不然会收不到内容(即使邮件发送成功)。
31 #可以将图片装入一个MIMEMultipart对象中,再将此MIMEMultipart和文本一起放入另一个MIMEMultipart对象中
32 msg_image = email.mime.multipart.MIMEMultipart('alternative')
33 msg.attach(msg_image)
34 
35 #邮件正文
36 content = '''
37 <p>python 邮件发送测试</p>
38 <p>图片演示: </p>
39 <p><img src = "cid:image1"></p>
40 '''
41 
42 txt = email.mime.text.MIMEText(content, 'html', 'utf-8')
43 msg.attach(txt)
44 
45 #读取图片并添加邮件头
46 fp = open('D://photos/test.jpg', 'rb')
47 m_image = email.mime.image.MIMEImage(fp.read())
48 fp.close()
49 
50 m_image.add_header('Content-ID', '<image1>')
51 msg_image.attach(m_image)
52 
53 indx = 50
54 while indx:
55     try:
56         smtp = smtplib.SMTP()
57         smtp.connect('smtp.163.com', '25')
58         smtp.login(sender, pwd)
59         smtp.sendmail(sender, receiver, msg.as_string())
60         smtp.quit()
61         print('email sent successfully!')
62         break;
63     except smtplib.SMTPException as e:
64         print('email failed!
%s' % e)
65     print('')
66     indx -= 1
View Code

注意:不能直接将图片和文本一起放到一个 MIMEMultipart 对象中,不然会收不到内容(即使邮件发送成功)。可以将图片装入一个 MIMEMultipart 对象中,再将此 MIMEMultipart 和文本一起放入另一个 MIMEMultipart 对象中

163 邮箱 554 错误:

554 DT:SPM 发送的邮件内容包含了未被许可的信息,或被系统识别为垃圾邮件。请检查是否有用户发送病毒或者垃圾邮件;

554 DT:SUM 信封发件人和信头发件人不匹配;

554 IP is rejected, smtp auth error limit exceed 该IP验证失败次数过多,被临时禁止连接。请检查验证信息设置;

554 HL:IHU 发信IP因发送垃圾邮件或存在异常的连接行为,被暂时挂起。请检测发信IP在历史上的发信情况和发信程序是否存在异常;

554 HL:IPB 该IP不在网易允许的发送地址列表里;

554 MI:STC 发件人当天内累计邮件数量超过限制,当天不再接受该发件人的投信。请降低发信频率;

554 MI:SPB 此用户不在网易允许的发信用户列表里;

554 IP in blacklist 该IP不在网易允许的发送地址列表里。

pop3 接收邮件

收取邮件就是编写一个 MUA 作为客户端,从 MDA 获取邮件到用户的电脑或手机上。Python 内置了一个 poplib 模块,用于实习 pop3 协议,可以直接用来接收邮件。

注意:pop3 协议收取的不是可以阅读的邮件,而不是邮件的文本。还需要用 email 模块提供的各种类解析原始文本

收取邮件分为以下两个步骤:

1.用 poplib 把邮件的原始文本下载到本地

2. 用 email 解析原始文本,还原为邮件对象

代码:

  1 #!/usr/python3
  2 #-*-coding:utf-8-*-
  3 
  4 from email.parser import Parser
  5 from email.header import decode_header
  6 from email.utils import parseaddr
  7 import poplib
  8 
  9 
 10 # 编码转换
 11 def decode_str(s):
 12     value, charset = decode_header(s)[0]
 13     if charset:
 14         value = value.decode(charset)
 15     return value
 16 
 17 
 18 def guess_charset(msg):
 19     charset = msg.get_charset()
 20     if charset is None:
 21         content_type = msg.get('Content-Type', ).lower()
 22         pos = content_type.find('charset=')
 23         if pos >= 0:
 24             charset = content_type[pos + 8:].strip()
 25     return charset
 26 
 27 
 28 # indent用于缩进显示
 29 def print_info(msg, indent = 0):
 30     if indent == 0:
 31         for header in ['From', 'To', 'Subject']:
 32             value = msg.get(header,)
 33             if value:
 34                 if header == 'Subject':
 35                     value = decode_str(value)
 36                 else:
 37                     hdr, addr = parseaddr(value)
 38                     name = decode_str(hdr)
 39                     value = u'%s<%s>'%(name, addr)
 40             print('%s%s:%s' % (' '*indent, header, value))
 41     if(msg.is_multipart()):
 42         parts = msg.get_payload()
 43         for n, part in enumerate(parts):
 44             print('%spart %s' % (' '*indent, n))
 45             print('%s---------------' % (' ' * indent))
 46             print_info(part, indent + 1)
 47     else:
 48         content_type = msg.get_content_type()
 49         if(content_type == 'text/plain' or content_type == 'text/html'):
 50             content = msg.get_payload(decode = True)
 51             charset = guess_charset(msg)
 52             if charset:
 53                 content = content.decode(charset)
 54             print('%sText: %s' % (' ' *indent, content + '...'))
 55         else:
 56             print('%sAttachment:%s' % (' '*indent, content_type))
 57 
 58 
 59 
 60 #输入邮件地址、口令和pop3服务器地址
 61 pwd_file = open('163mail.txt', 'r')
 62 sender_file = open('senders.txt', 'r')
 63 
 64 email = sender_file.read()
 65 password = pwd_file.read()
 66 pop3_server = 'pop.163.com'
 67 
 68 pwd_file.close()
 69 sender_file.close()
 70 
 71 #连接到pop3服务器
 72 server = poplib.POP3(pop3_server)
 73 #可以打开或关闭调试信息
 74 server.set_debuglevel(1)
 75 #可选:输出pop3服务器的欢迎文字
 76 print(server.getwelcome().decode('utf-8'))
 77 
 78 #身份认证
 79 server.user(email)
 80 server.pass_(password)
 81 
 82 #stat()返回邮件数量和占用空间
 83 Messages,Size = server.stat()
 84 print('Messages:%s. Size:%s' % (Messages, Size))
 85 #list()返回所有邮件的编号
 86 resp,mails,octets = server.list()
 87 #查看返回列表
 88 print(mails)
 89 
 90 #获取最新一封邮件,注意索引号从1开始
 91 index = len(mails)
 92 resp,lines,octets = server.retr(index)
 93 
 94 #lines存储了邮件原始文本的每一行
 95 #可以获得整个邮件的原始文本
 96 msg_content = b'
'.join(lines).decode('utf-8')
 97 #解析邮件
 98 msg = Parser().parsestr(msg_content)#将邮件内容解析为Messege对象
 99 print_info(msg, index)
100 # print('\\\\\\')
101 # print_info(msg, index - 1)
102 
103 #可以根据邮件索引号直接从服务器删除邮件
104 #server.dele(index)
105 # for i in range(1, Messages + 1):
106 #     server.dele(i)
107 server.quit()
View Code

上面的代码文件解析的还是有些混乱,本来打算整个简单的收发邮件的客户端也没弄。打个比赛回来啥都不想动了,以后要用的时候再来完善好了。

原文地址:https://www.cnblogs.com/geloutingyu/p/8996512.html