【智控万物】微信QQ邮件温度计
本帖最后由 云天 于 2021-1-26 20:51 编辑【项目设计】
可通过微信直接看到家里的室温,不用打开微信小程序或其它APP。使用Mind+中 Python 模式“PinPong库”。
【PinPong库】
PinPong库是一套控制开源硬件主控板的Pyhton库,基于Firmata协议并兼容MicroPython语法,5分钟即可让你上手使用Python控制开源硬件。借助于PinPong库,直接用Python代码就能给各种常见的开源硬件编程。其原理是给开源硬件烧录一个特定的固件,使开源硬件可以通过串口与电脑通讯,执行各种命令。PinPong库的名称由“Pin”和“Pong”组成,“Pin”指引脚,“PinPong”为“乒乓球”的谐音,指信号的往复。pinpong库的设计,是为了让开发者在开发过程中不用被繁杂的硬件型号束缚,而将重点转移到软件的实现。哪怕程序编写初期用Arduino开发,部署时改成了掌控板,只要修改一下硬件的参数就能正常运行,实现了“一次编写处处运行”。
【Mind+ Python模式】
http://mindplus.cc/
【开启POP3/SMTP服务】
因要向QQ邮箱发送邮件,所以要设置自己的QQ邮箱开启POP3/SMTP服务,同时通过手机发送验证短信,生成授权码。
Forgotten补充设置过程图片
【微信开启QQ邮箱提醒】
https://kf.qq.com/touch/faq/1506 ... Uz.html?platform=14
【硬件】
主控板使用Arduino uno,温度传感器为:LM35线性模拟温度传感器
连接示意图
【代码编写】
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
import time
from pinpong.board import Board,Pin,ADC
Board("uno").begin()
adc0 = Pin(Pin.A0, Pin.ANALOG)
my_sender='********@qq.com' # 发件人邮箱账号
my_pass = 'syzwyzj***xuqbgbi' # 发件人邮箱密码(授权码)
my_user='*******@qq.com' # 收件人邮箱账号,我这边发送给自己
def mail(Form,Form_name,Password,To,To_name,Title,Content):
ret=True
try:
msg=MIMEText(Title,'plain','utf-8')
msg['From']=formataddr()# 括号里的对应发件人邮箱昵称、发件人邮箱账号
msg['To']=formataddr() # 括号里的对应收件人邮箱昵称、收件人邮箱账号
msg['Subject']=Content # 邮件的主题,也可以说是标题
server=smtplib.SMTP_SSL("smtp.qq.com", 465)# 发件人邮箱中的SMTP服务器,端口是25
server.login(Form, Password)# 括号中对应的是发件人邮箱账号、邮箱密码
server.sendmail(Form,,msg.as_string())# 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
server.quit()# 关闭连接
except Exception:# 如果 try 中的语句没有执行,则会执行下面的 ret=False
ret=False
return ret
while True:
v = adc0.read_analog()
tem = round(v*(5/10.24),1)
print(tem)
ret=mail(my_sender,"QQ邮件温度计",my_pass,my_user,"温度","当前室内温度为",str(tem)+"℃")
if ret:
print("邮件发送成功")
else:
print("邮件发送失败")
time.sleep(60)
【邮件协议】
发送邮件——SMTP协议
SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP协议属于TCP/IP协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。通过SMTP协议所指定的服务器,就可以把E-mail寄到收信人的服务器上了,只要几分钟。
接收邮件——POP3和IMAP
POP是指邮局协议,目的是让用户可以访问邮箱服务器中的邮件,允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的。
后来又出现了IMAP协议(Interactive Mail Access Protocol),即交互式邮件访问协议,与POP3的不同在于:开启了IMAP后,在电子邮件客户端收取的邮件仍然保留在服务器上,同时在客户端上的操作都会反馈到服务器上,如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作。
【发送邮件,获取室内温度】
以下代码实现,每60秒测试一次邮箱中是否有主题为“温度”的邮件。如果有,发送当前温度到邮箱。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import poplib
import datetime
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
import time
from pinpong.board import Board,Pin,ADC
Board("uno").begin()
adc0 = Pin(Pin.A0, Pin.ANALOG)
my_sender='********@qq.com' # 发件人邮箱账号
my_pass = 'syzwy*****qbgbi' # 发件人邮箱密码(授权码)
my_user='*********@qq.com' # 收件人邮箱账号,我这边发送给自己
# 此函数通过使用poplib实现接收邮件
def recv_email_by_pop3(QQ_Address,Password):
# 要进行邮件接收的邮箱。改成自己的邮箱
email_address = QQ_Address
# 要进行邮件接收的邮箱的密码。改成自己的邮箱的密码
# 设置 -> 账户 -> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 -> 开启服务:POP3/SMTP服务
# 设置 -> 账户 -> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 -> 生成授权码
email_password = Password
# 邮箱对应的pop服务器,也可以直接是IP地址
# 改成自己邮箱的pop服务器;qq邮箱不需要修改此值
pop_server_host = "pop.qq.com"
# 邮箱对应的pop服务器的监听端口。改成自己邮箱的pop服务器的端口;qq邮箱不需要修改此值
pop_server_port = 995
try:
# 连接pop服务器。如果没有使用SSL,将POP3_SSL()改成POP3()即可其他都不需要做改动
email_server = poplib.POP3_SSL(host=pop_server_host, port=pop_server_port, timeout=10)
print("pop3----connect server success, now will check username")
except:
print("pop3----sorry the given email server address connect time out")
exit(1)
try:
# 验证邮箱是否存在
email_server.user(email_address)
print("pop3----username exist, now will check password")
except:
print("pop3----sorry the given email address seem do not exist")
exit(1)
try:
# 验证邮箱密码是否正确
email_server.pass_(email_password)
print("pop3----password correct,now will list email")
except:
print("pop3----sorry the given username seem do not correct")
exit(1)
# 邮箱中其收到的邮件的数量
email_count = len(email_server.list()[1])
# list()返回所有邮件的编号:
resp, mails, octets = email_server.list()
# 遍历所有的邮件
if len(mails)>0 :
#for i in range(1, len(mails) + 1):#这里只读最新收到的邮件
# 通过retr(index)读取第index封邮件的内容;这里读取最后一封,也即最新收到的那一封邮件
resp, lines, octets = email_server.retr(len(mails))
# lines是邮件内容,列表形式使用join拼成一个byte变量
email_content = b'\r\n'.join(lines)
try:
# 再将邮件内容由byte转成str类型
email_content = email_content.decode('utf-8')
except Exception as e:
print(str(e))
# # 将str类型转换成<class 'email.message.Message'>
# msg = email.message_from_string(email_content)
msg = Parser().parsestr(email_content)
return(parse_email(msg, 0))
# 关闭连接
email_server.close()
def parse_email(msg, indent):
if indent == 0:
# 邮件的From, To, Subject存在于根对象上:
for header in ['From', 'To', 'Subject']:
value = msg.get(header, '')
if value:
if header=='Subject':
# 需要解码Subject字符串:
value = decode_str(value)
print(value)
return value
else:
# 需要解码Email地址:
hdr, addr = parseaddr(value)
name = decode_str(hdr)
value = u'%s <%s>' % (name, addr)
#print('%s%s: %s' % ('' * indent, header, value))
# 解码
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
# 猜测字符编码
def guess_charset(msg):
# 先从msg对象获取编码:
charset = msg.get_charset()
if charset is None:
# 如果获取不到,再从Content-Type字段获取:
content_type = msg.get('Content-Type', '').lower()
for item in content_type.split(';'):
item = item.strip()
if item.startswith('charset'):
charset = item.split('=')[1]
break
return charset
def mail(Form,Form_name,Password,To,To_name,Title,Content):
ret=True
try:
msg=MIMEText(Title,'plain','utf-8')
msg['From']=formataddr()# 括号里的对应发件人邮箱昵称、发件人邮箱账号
msg['To']=formataddr() # 括号里的对应收件人邮箱昵称、收件人邮箱账号
msg['Subject']=Content # 邮件的主题,也可以说是标题
server=smtplib.SMTP_SSL("smtp.qq.com", 465)# 发件人邮箱中的SMTP服务器,端口是25
server.login(Form, Password)# 括号中对应的是发件人邮箱账号、邮箱密码
server.sendmail(Form,,msg.as_string())# 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
server.quit()# 关闭连接
except Exception:# 如果 try 中的语句没有执行,则会执行下面的 ret=False
ret=False
return ret
while True:
if recv_email_by_pop3(my_sender,my_pass)=="温度":
v = adc0.read_analog()
tem = round(v*(5/10.24),1)
print(tem)
ret=mail(my_sender,"QQ邮件温度计",my_pass,my_user,"温度","当前室内温度为",str(tem)+"℃")
if ret:
print("邮件发送成功")
else:
print("邮件发送失败")
time.sleep(60)
这个很不错诶! 邮件服务 赞啦 有用,收藏了
强,学习一波 本帖最后由 Forgotten 于 2021-1-26 19:56 编辑
测试成功,非常方便,感谢楼主补充一下,在设置>账户中开启POP
Forgotten 发表于 2021-1-26 19:51
测试成功,非常方便,感谢楼主补充一下,在设置>账户中开启POP
已增加,感谢!
页:
[1]