下载地址:https://www.pan38.com/dow/share.php?code=JCnzE 提取密码:1139
该实现包含SMTP协议通信、Excel读取、HTML模板、多线程控制等功能模块。使用时需要先申请163邮箱的SMTP授权码,配置在config.ini中。批量发送时按照Excel表格中的收件人、主题和内容进行发送
import smtplib
import openpyxl
import threading
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
import time
import random
class MailSender:
def __init__(self, config):
self.smtp_server = 'smtp.163.com'
self.smtp_port = 465
self.username = config['username']
self.password = config['password']
self.sender = config['sender']
self.max_threads = config.get('max_threads', 5)
self.delay = config.get('delay', 1)
self.semaphore = threading.Semaphore(self.max_threads)
def _connect_server(self):
server = smtplib.SMTP_SSL(self.smtp_server, self.smtp_port)
server.login(self.username, self.password)
return server
def _build_message(self, receiver, subject, content, attachments=None):
msg = MIMEMultipart()
msg['From'] = Header(self.sender)
msg['To'] = Header(receiver)
msg['Subject'] = Header(subject)
msg.attach(MIMEText(content, 'html', 'utf-8'))
if attachments:
for att in attachments:
with open(att, 'rb') as f:
att_part = MIMEApplication(f.read())
att_part.add_header(
'Content-Disposition',
'attachment',
filename=os.path.basename(att)
)
msg.attach(att_part)
return msg
def send_single(self, receiver, subject, content, attachments=None):
try:
with self.semaphore:
server = self._connect_server()
msg = self._build_message(receiver, subject, content, attachments)
server.sendmail(self.sender, receiver, msg.as_string())
server.quit()
time.sleep(self.delay + random.random())
return True
except Exception as e:
print(f"发送失败 {receiver}: {str(e)}")
return False
def batch_send(self, excel_path, sheet_name='Sheet1'):
wb = openpyxl.load_workbook(excel_path)
ws = wb[sheet_name]
threads = []
for row in ws.iter_rows(min_row=2, values_only=True):
receiver, subject, content = row[0], row[1], row[2]
t = threading.Thread(
target=self.send_single,
args=(receiver, subject, content)
)
threads.append(t)
t.start()
for t in threads:
t.join()
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.header { background-color: #f8f8f8; padding: 10px; text-align: center; }
.content { padding: 20px 0; }
.footer { border-top: 1px solid #eee; padding-top: 10px; font-size: 0.8em; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>{{header}}</h1>
</div>
<div class="content">
{{content}}
</div>
<div class="footer">
<p>此邮件由系统自动发送,请勿直接回复</p>
</div>
</div>
</body>
</html>
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。