如何提升SMTP消息发送速度?多次调用延迟且线程方案失效
优化SMTP消息发送速度的解决方案
问题根源
原代码每次调用send_message都会重复执行SMTP连接建立、TLS握手、登录操作,这些步骤本身耗时较长,连续调用多次会累积延迟,导致消息发送间隔过大。之前的线程方案未成功,大概率是因为每个线程仍重复创建独立连接,反而增加了系统开销和邮箱限流风险。
核心优化方案:复用SMTP连接
最有效的优化方式是只建立一次SMTP连接,用同一个连接发送多条消息,省去重复连接、登录的耗时步骤。
1. 封装复用连接的客户端类
import smtplib # 假设已定义以下全局变量 CARRIERS = { "att": "@mms.att.net", "verizon": "@vtext.com" } EMAIL = "your_email@gmail.com" PASSWORD = "your_app_password" # Gmail需使用应用专用密码,而非登录密码 class SMTPClient: def __init__(self, smtp_server, smtp_port, email, password): self.smtp_server = smtp_server self.smtp_port = smtp_port self.email = email self.password = password self.server = None def connect(self): """建立SMTP连接并完成登录""" self.server = smtplib.SMTP(self.smtp_server, self.smtp_port) self.server.starttls() self.server.login(self.email, self.password) def send_message(self, phone_number, carrier, message): """发送单条消息,需先调用connect()建立连接""" if not self.server: raise RuntimeError("请先调用connect()初始化连接") recipient = phone_number + CARRIERS[carrier] self.server.sendmail(self.email, recipient, message) def close(self): """关闭SMTP连接,避免资源泄漏""" if self.server: self.server.quit()
2. 批量发送示例
# 初始化客户端并建立一次连接 client = SMTPClient("smtp.gmail.com", 587, EMAIL, PASSWORD) client.connect() try: # 一次性发送多条消息,复用同一连接 client.send_message("1234567890", "att", "第一条消息") client.send_message("0987654321", "verizon", "第二条消息") client.send_message("1122334455", "att", "第三条消息") finally: # 发送完成后必须关闭连接 client.close()
线程异步优化方案(正确实现)
如果需要异步提交发送任务,可采用单线程复用连接+消息队列的方式,避免多线程竞争连接资源:
import queue import threading # 创建消息队列用于存放待发送任务 message_queue = queue.Queue() def message_worker(client): """工作线程:从队列取任务并复用连接发送""" while True: try: phone_num, carrier, msg = message_queue.get() if phone_num is None: # 接收退出信号 break client.send_message(phone_num, carrier, msg) message_queue.task_done() except Exception as e: print(f"消息发送失败: {str(e)}") message_queue.task_done() # 初始化客户端并启动工作线程 client = SMTPClient("smtp.gmail.com", 587, EMAIL, PASSWORD) client.connect() worker_thread = threading.Thread(target=message_worker, args=(client,)) worker_thread.start() # 提交发送任务到队列 message_queue.put(("1234567890", "att", "异步发送第一条")) message_queue.put(("0987654321", "verizon", "异步发送第二条")) message_queue.put(("1122334455", "att", "异步发送第三条")) # 等待所有任务完成,发送退出信号并关闭资源 message_queue.join() message_queue.put((None, None, None)) worker_thread.join() client.close()
额外注意事项
- Gmail权限设置:需开启两步验证并创建应用专用密码,避免登录失败。
- 发送频率限制:Gmail普通账户单日发送上限为500条,短时间内大量发送可能触发临时限流,若发送量较大需分批次控制速率。
- 连接异常处理:实际使用中需添加连接重连逻辑,避免因网络波动导致发送失败。
内容的提问来源于stack exchange,提问作者Ethan Varghese
相关产品推荐
相关产品推荐

