需求说明
每日定时发送邮件,邮件中包含excel数据
发送邮件代码
# -*- coding:utf-8 -*-
import email, smtplib, ssl
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import time
smtp_server = "smtp.exmail.qq.com"
sender_email = "analysis@test.com" # Enter your address
password = "1234"
port = 25
receiver_email = ["test@gmail.com"] # Enter receiver address
subject = "测试邮件主题"
body = """测试邮件内容"""
# 发送方法,file_name是发送附件的路径与名称
def send_email(file_name):
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
# mime message must be strings
message["To"] = ', '.join(receiver_email)
subjectTxt = subject.format(time.strftime('%Y%m%d%H%M',time.localtime(time.time())))
message["Subject"] = subjectTxt
# mime message must be strings
message["Bcc"] = ', '.join(receiver_email) # Recommended for mass emails
# Add body to email
message.attach(MIMEText(body.format(subjectTxt), "plain"))
# Open PDF file in binary mode
with open(file_name, "rb") as attachment:
# Add file as application/octet-stream
# Email client can usually download this automatically as attachment
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode file in ASCII characters to send by email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= {file_name}",
)
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
# Log in to server using secure context and send email
context = ssl.create_default_context()
with smtplib.SMTP(smtp_server, port) as server:
server.ehlo() # Can be omitted
server.starttls(context=context)
server.ehlo() # Can be omitted
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, text)
这里是关键的发邮件代码,执行send_email方法,相对路径+文件名称作为参数,即可发送邮件。本地测试成功后即可部署到服务器
部署到阿里云服务器
前置准备:请自行安装python3
本地测试成功,部署到阿里云服务器,出现异常:
File "/data/scripts/cps-email/SendEmail.py", line 64, in send_email
with smtplib.SMTP(smtp_server, port) as server:
File "/usr/local/python-3.6.7/lib/python3.6/smtplib.py", line 251, in __init__
(code, msg) = self.connect(host, port)
File "/usr/local/python-3.6.7/lib/python3.6/smtplib.py", line 338, in connect
(code, msg) = self.getreply()
File "/usr/local/python-3.6.7/lib/python3.6/smtplib.py", line 394, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
异常原因:
代码中使用发送邮件服务的端口是25,在阿里云上是不安全端口
解决方法:
- 端口换成:456
- 修改代码
原代码:
# Log in to server using secure context and send email
context = ssl.create_default_context()
with smtplib.SMTP(smtp_server, port) as server:
server.ehlo() # Can be omitted
server.starttls(context=context)
server.ehlo() # Can be omitted
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, text)
改成如下:
# Log in to server using secure context and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, port) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, text)
再次执行脚本成功发送
使用crontab定时执行Python脚本
如果是直接在crontab中执行python脚本:
*/1 * * * * python3 /data/scripts/cps-email/Report.py /data/scripts/cps-email/run.log 2>&1
会出现脚本中文件路径错误问题,必须使用绝对路径。因为crontab执行脚本时根目录是python3的安装路径
解决办法是把执行语句放入shell脚本中执行:
#发送cps邮件数据
#!/bin/bash
#切换到脚本目录
cd /data/scripts/cps-email/
python3 /data/scripts/cps-email/Report.py
再把shell脚本部署到crontab中:
*/1 * * * * sh /data/scripts/cps-email/sendCpsEmail.sh >> /data/scripts/cps-email/run.log 2>&1
测试成功,大功告成!