简单的文本邮件
代码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)
代码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!\n%s\' % e)
发送 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)
发送带附件的邮件
带附件的邮件可以看作包含文本和各个附件,可以构建一个 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!\n%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)
发送图片
代码:
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!\n%s\' % e) 65 print(\'\') 66 indx -= 1
注意:不能直接将图片和文本一起放到一个 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\'\r\n\'.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()
上面的代码文件解析的还是有些混乱,本来打算整个简单的收发邮件的客户端也没弄。打个比赛回来啥都不想动了,以后要用的时候再来完善好了。