Python邮件
发送纯文本邮件(此案例发送接收成功)
1 import smtplib 2 from email.mime.text import MIMEText 3 4 ''' 5 MIMEText三个主要参数 6 1.邮件内容 7 2.MIME子类型,此案例用plain表示text类型 8 3.邮件编码格式 9 ''' 10 msg = MIMEText('这是邮件内容', 'plain', 'utf-8') 11 from_addr = '18555251650@qq.com' 12 pwd = 'dlgrhegpprgdcbbf' #这个不是密码,是腾讯邮箱授权码,类似密码 13 to = '18555251650@qq.com' 14 smtp_srv = 'smtp.qq.com' 15 16 try: 17 srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) 18 srv.login(from_addr, pwd) 19 srv.sendmail(from_addr, [to], msg.as_string()) #[to]也可以用to,字符串也可以,详见API代码注释 20 srv.quit() 21 except Exception as e: 22 print(e)
发送HTML格式邮件(此案例发送接收成功,邮件正文带表格)
1 import smtplib 2 from email.mime.text import MIMEText 3 4 mail_content = ''' 5 <!DOCTYPE html> 6 <html lang="en"> 7 <head> 8 <meta charset="UTF-8"> 9 <title>这是标题</title> 10 </head> 11 <body> 12 <h1>这是一封HTML格式邮件</h1> 13 <table border=2> 14 <tr><td>第一行第一列</td><td>第一行第二列</td></tr> 15 <tr><td>第二行第一列</td><td>第二行第二列</td></tr> 16 </table> 17 </body> 18 </html> 19 ''' 20 21 msg = MIMEText(mail_content, 'html', 'utf-8') 22 from_addr = '18555251650@qq.com' 23 pwd = 'dlgrhegpprgdcbbf' 24 to = ['18555251650@qq.com'] 25 smtp_srv = 'smtp.qq.com' 26 try: 27 srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) 28 srv.login(from_addr, pwd) 29 srv.sendmail(from_addr, to, msg.as_string()) 30 except Exception as e: 31 print(e)
发送带附件的邮件(此案例发送接收成功)
1 import smtplib 2 from email.mime.text import MIMEText # 构建附件使用 3 from email.mime.multipart import MIMEMultipart # 构建基础邮件使用 4 5 mail_mul = MIMEMultipart() 6 # 构建邮件正文 7 mail_text = MIMEText('这是邮件正文', 'plain', 'utf-8') 8 # 把构建好的邮件正文附件加邮件中 9 mail_mul.attach(mail_text) 10 11 with open('附件.jpg', 'rb') as f: 12 s = f.read() 13 # 设置附件的MIME和文件名 14 m = MIMEText(s, 'base64', 'utf-8') 15 m['Content-Type'] = 'application/octet-stream' 16 m['Content-Disposition'] = 'attachment;filename="abc.jpg"' # 附件名若为中文收到的邮件附件名会有问题 17 mail_mul.attach(m) 18 19 from_addr = '18555251650@qq.com' 20 pwd = 'dlgrhegpprgdcbbf' 21 to = ['18555251650@qq.com'] 22 smtp_srv = 'smtp.qq.com' 23 24 try: 25 srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) 26 srv.login(from_addr, pwd) 27 srv.sendmail(from_addr, to, mail_mul.as_string()) 28 srv.quit() 29 except Exception as e: 30 print(e)
发送邮件带From, To, Subject,即发送者,接收者,标题(此案例发送接收成功)
1 import smtplib 2 from email.mime.text import MIMEText 3 from email.header import Header 4 5 msg = MIMEText('这是邮件正文', 'plain', 'utf-8') 6 7 msg['From'] = Header('从这里发出去的', 'utf-8') 8 msg['To'] = Header('发到这个地方去', 'utf-8') 9 msg['Subject'] = Header('这个是标题', 'utf-8') 10 11 from_addr = '18555251650@qq.com' 12 pwd = 'dlgrhegpprgdcbbf' 13 to = ['18555251650@qq.com'] 14 15 smtp_srv = 'smtp.qq.com' 16 17 try: 18 srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) 19 srv.login(from_addr, pwd) 20 srv.sendmail(from_addr, to, msg.as_string()) 21 srv.quit() 22 except Exception as e: 23 print(e)
发送同时带纯文件和HTML内容的邮件(此案例发送接收成功)
1 import smtplib 2 from email.mime.text import MIMEText 3 from email.mime.multipart import MIMEMultipart 4 5 msg = MIMEMultipart('alternative') 6 7 html_content = ''' 8 <!DOCTYPE html> 9 <html lang="en"> 10 <head> 11 <meta charset="UTF-8"> 12 <title>这是标题</title> 13 </head> 14 <body> 15 <h1>这是一封HTML格式邮件</h1> 16 <table border=2> 17 <tr><td>第一行第一列</td><td>第一行第二列</td></tr> 18 <tr><td>第二行第一列</td><td>第二行第二列</td></tr> 19 </table> 20 </body> 21 </html> 22 ''' 23 24 msg_html = MIMEText(html_content, 'html', 'utf-8') 25 msg.attach(msg_html) 26 msg_text = MIMEText('这是纯文本邮件正文', 'plain', 'utf-8') # 收到的邮件中看不到这个内容 27 msg.attach(msg_text) 28 29 from_addr = '18555251650@qq.com' 30 pwd = 'dlgrhegpprgdcbbf' 31 to = ['18555251650@qq.com'] 32 33 smtp_srv = 'smtp.qq.com' 34 35 try: 36 # server = smtplib.SMTP_SSL(smtp_srv.encode(), 465) # 加密传输 37 server = smtplib.SMTP(smtp_srv.encode(), 25) # qq邮箱要求使用TLS加密传输 38 server.starttls() 39 # server.set_debuglevel(1) # 设置调试级别 40 server.login(from_addr, pwd) 41 server.sendmail(from_addr, to, msg.as_string()) 42 server.quit() 43 except Exception as e: 44 print(e)
接收邮件(此案例接收解析查看邮件成功)
1 import poplib # 负责从MDA到MUA下载 2 # 以下包负责相关邮件结构解析 3 from email.parser import Parser 4 from email.header import decode_header 5 from email.utils import parseaddr 6 7 8 # 得到邮件的原始内容,这个过程主要负责从MDA到MUA的下载并使用Parse粗略解析 9 def getMsg(): 10 email = '18555251650@qq.com' 11 pwd = 'dlgrhegpprgdcbbf' 12 pop3_srv = 'pop.qq.com' # 端口995 13 srv = poplib.POP3_SSL(pop3_srv) # SSL代表是安全通道 14 srv.user(email) # user代表email地址 15 srv.pass_(pwd) # pass_代表密码 16 17 # 以下操作根据具体业务具体使用 18 # stat返回邮件数量和占用空间 19 # 注意stat返回一个tuple格式 20 msgs, counts = srv.stat() 21 print('msgs=', msgs) 22 print('counts=', counts) 23 24 # list返回所有邮件编号列表 25 # mails是所有邮件编号列表 26 rsp, mails, octets = srv.list() 27 # 可以查看返回的mails列表类似 [b'1 3946', b'2 2309', b'3 29794', ……] 28 print('mails=', mails) 29 30 # 获取最新一封邮件,注意,邮件索引号是从1开始,最新代表索引最高 31 index = len(mails) 32 # retr负责返回一个具体索引号的一封信的内容,此内容不具有可读性 33 # lines存储邮件的最原始文本的每一行 34 rsp, lines, octets = srv.retr(index) 35 36 # 获得整个邮件的原始文本 37 msg_count = b'\r\n'.join(lines).decode('utf-8') 38 # 解析出邮件整个结构体 39 # 参数是解码后的邮件整个 40 msg = Parser().parsestr(msg_count) 41 42 srv.quit() # 关闭链接 43 return msg 44 45 46 # 详细解析得到的邮件内容 47 # msg代表是邮件的原始内容 48 # ident代表的是邮件嵌套的层级 49 def parseMsg(msg, indent=0): 50 ''' 51 1.邮件完全可能是有嵌套格式 52 2.邮件只有一个From, To,Subject之类的信息 53 3.indent:描述邮件里面有几个邮件MIMEXXX类型的内容,展示的时候进行相应缩进 54 ''' 55 # 想办法提取出头部信息 56 # 只有在第一层的邮件中才会有相关内容 57 # 此内容只有一个 58 if indent == 0: 59 for header in ['From', 'To', 'Subject']: 60 # 使用get可以避免如果没有相关关键字报错的可能性 61 # 如果没有关键字‘From’,我们使用msg['From']会报错 62 value = msg.get(header, '') 63 if value: 64 # Subject中的内容直接解码就可以,他是字符串类型 65 if header == 'Subject': 66 value = decodeStr(value) 67 # 如果是From和To字段,则内容大概是‘我的邮箱<xxx@qq.com>’这种格式 68 else: 69 hdr, addr = parseaddr(value) 70 name = decodeStr(hdr) 71 # 最终返回形如‘我的邮箱<xxx@qq.com>’的格式 72 value = '{}<{}'.format(name, addr) 73 print('indent=', indent, 'header=', header, 'value=', value) 74 75 # 下面代码关注邮件内容本身 76 # 邮件内容中,有可能是multipart类型,也有可能是普通邮件类型 77 # 下面的解析使用递归方式 78 if (msg.is_multipart()): 79 # 如果是multipart类型,则调用递归解析 80 # 得到多部分邮件的一个基础邮件部分 81 parts = msg.get_payload() 82 # enumerate函数是内置函数 83 # 作用是将一个列表,此处是parts,生成一个有索引和parts原内容构成的新的列表 84 # 例如enumerate(['a','b','c'])结果是:[(1,'a'),(2,'b'),(3,'c')] 85 for n, part, in enumerate(parts): 86 print('{}spart:{}'.format(' ' * indent, n)) 87 parseMsg(part, indent + 1) 88 else: # 基础类型 89 # get_content_type是系统提供函数,得到内容类型 90 content_type = msg.get_content_type() 91 if content_type == 'text/plain' or content_type == 'text/html': 92 content = msg.get_payload(decode=True) 93 charset = guessCharset(msg) 94 if charset: 95 content = content.decode(charset) 96 print('{}Text:{}'.format(indent, content)) 97 else: # 不是文本内容,则应该是附件 98 print('{}Attachment:{}'.format(indent, content_type)) 99 100 101 def decodeStr(s): 102 ''' 103 s代表一封邮件中From,To,Subject中的任一项 104 对s进行解码,解码是编码的逆过程 105 ''' 106 value, charset = decode_header(s)[0] 107 # cahrset完全可能为空 108 if charset: 109 # 如果指定编码,则用指定编码格式进行解码 110 value = value.decode(charset) 111 return value 112 113 114 def guessCharset(msg): 115 charset = msg.get_charset() 116 if charset is None: 117 content_type = msg.get('Content-Type', '').lower() 118 pos = content_type.find('charset=') 119 if pos >= 0: 120 charset = content_type[pos + 8:].strip() 121 return charset 122 123 124 if __name__ == '__main__': 125 msg = getMsg() # 得到邮件的原始内容 126 print(msg) 127 parseMsg(msg, 0) # 精确解析邮件内容