Python中如何实现邮件实时收取功能?
用 python 写了个下载邮件附件的脚本,在 windows 计划任务里做了个 1 分钟循环定时。有没有办法改成实时接收?如果写 while 循环的话,一直重复登录邮箱是不是不太好,能否实现监听邮箱有新邮件再运行
Python中如何实现邮件实时收取功能?
IMAP POP3 都没有推送,只能定时查询
Exchange ActiveSync 了解下
import imaplib
import email
from email.header import decode_header
import time
class EmailMonitor:
def __init__(self, username, password, imap_server='imap.gmail.com'):
self.username = username
self.password = password
self.imap_server = imap_server
self.mail = None
self.last_uid = 0 # 记录最后处理的邮件UID
def connect(self):
"""建立IMAP连接"""
self.mail = imaplib.IMAP4_SSL(self.imap_server)
self.mail.login(self.username, self.password)
self.mail.select('INBOX')
def get_new_emails(self):
"""获取新邮件"""
# 搜索所有未读邮件
status, messages = self.mail.search(None, 'UNSEEN')
if status != 'OK':
return []
email_ids = messages[0].split()
new_emails = []
for e_id in email_ids:
# 获取邮件内容
status, msg_data = self.mail.fetch(e_id, '(RFC822)')
if status != 'OK':
continue
# 解析邮件
raw_email = msg_data[0][1]
msg = email.message_from_bytes(raw_email)
# 解码邮件主题
subject, encoding = decode_header(msg['Subject'])[0]
if isinstance(subject, bytes):
subject = subject.decode(encoding if encoding else 'utf-8')
# 获取发件人
from_ = msg.get('From')
# 获取邮件正文
body = ''
if msg.is_multipart():
for part in msg.walk():
content_type = part.get_content_type()
content_disposition = str(part.get('Content-Disposition'))
if content_type == 'text/plain' and 'attachment' not in content_disposition:
body = part.get_payload(decode=True).decode()
break
else:
body = msg.get_payload(decode=True).decode()
new_emails.append({
'id': e_id.decode(),
'subject': subject,
'from': from_,
'body': body[:200] # 只取前200字符
})
return new_emails
def mark_as_read(self, email_id):
"""标记邮件为已读"""
self.mail.store(email_id, '+FLAGS', '\\Seen')
def monitor_loop(self, interval=30):
"""监控循环"""
print(f"开始监控邮箱: {self.username}")
print("按 Ctrl+C 停止监控\n")
try:
while True:
try:
new_emails = self.get_new_emails()
if new_emails:
print(f"发现 {len(new_emails)} 封新邮件:")
for email_data in new_emails:
print(f"\n主题: {email_data['subject']}")
print(f"发件人: {email_data['from']}")
print(f"内容预览: {email_data['body']}")
print("-" * 50)
# 标记为已读
self.mark_as_read(email_data['id'])
time.sleep(interval)
except Exception as e:
print(f"错误: {e}")
# 尝试重新连接
time.sleep(5)
self.connect()
except KeyboardInterrupt:
print("\n停止监控")
finally:
self.disconnect()
def disconnect(self):
"""断开连接"""
if self.mail:
self.mail.close()
self.mail.logout()
# 使用示例
if __name__ == "__main__":
# 配置你的邮箱信息
monitor = EmailMonitor(
username='your_email@gmail.com',
password='your_app_password' # 使用应用专用密码
)
# 连接邮箱
monitor.connect()
# 开始监控,每30秒检查一次
monitor.monitor_loop(interval=30)
核心要点:
- 使用
imaplib库实现IMAP协议连接 - 通过
search('UNSEEN')查找未读邮件 - 循环检查新邮件并解析内容
- 使用应用专用密码而非普通密码(Gmail需要)
注意替换your_email@gmail.com和your_app_password为实际值。对于Gmail,需要在设置中启用IMAP并生成应用专用密码。
一句话总结:用imaplib轮询检查UNSEEN邮件就行。
一直登录有啥不好?
其实 foxmail 这种也是定时去刷新登录的
IMAP IDLE 似乎可以
https://en.wikipedia.org/wiki/IMAP_IDLE
监控
邮件服务商没有提供可以推送的协议的话,就只能轮询了
自建邮件服务器就可以实时 其他登录后抓取就是了
你开着 Outlook 2016 然后用 Outlook object model 检查新邮件就行了。
自动转发到 sendcloud 或者 mailgun,然后创建一个收信路由。
首先 SMTP 不是 realtime 协议,所以我觉得实时收取这个需求本身是不存在的。
一定要尽量快的话,IMAP 有 Push 扩展可以试试(效果也就那样)
前端轮询, 或者后台轮询然后主动推给前端
小秘密:SMTP 甚至不是一个收信协议!
另一个小秘密:所有使用 Exchange 的用户都是实时收取的。
楼上已经说了,传统 Email 服务的协议 SMTP、POP3、IMAP 都是没有推送这一块的,所以你只能轮询。至于为什么这样设计,因为普通邮递就是这样的,不加钱就只送到邮箱。
我用的方法可能不高大上,但比较实用吧
直接转发到 QQ 邮箱,然后来邮件了微信就会马上滴滴滴
我用 GMail 收信比较及时,只慢一两分钟的样子,你自己写程序话,可以找找有 api 提供邮箱吧
SMTP 啊(如果你有公网 IP ),要知道以前的时候 sendmail 都是 Unix 发行版的标配。
另外 fetchmail 不了解一下?曾经电子邮件界的明星程序
SMTP 怎么不是收信协议了。SMTP 是简单邮件“传输”协议,传输包括收和发两部分!
msa 和 mta 前者发后者收和发,都是 SMTP 的实现。
当然不是收到信箱里,收到信箱里不叫收,叫“投递”
设置自动转发到自己服务器
#18 除非你是邮件服务器,目前我不 aware of 任何用 SMTP 收邮件的客户端。
但作为邮件服务器不存在“ SMTP 不实时”这种说法(它根本不 make sense ),因为邮件到达服务器才算收到,或者说服务器收到邮件的时刻才定义了这封邮件的“实时”。
#20
对啊,所以说 SMTP 并不能说“不是收信协议”。它是传输协议,既发也收
使用 SMTP 收信的客户端很多啊,MTA 都是啊,以前用的最多的就是 sendmail。这东西还是曾经很多 Unix 系统的标配。
怎么开?
我用的就是 Exchange,但 outlook 收信一直晚于网页是怎么回事,收集间隔设置的最小 1 分钟
一般实时的我都用 queue.get()
线程循环 queue.put()
你听得懂我在说什么吗?


