每日定时发送邮件,邮件中包含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,在阿里云上是不安全端口
解决方法:
原代码:
# 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脚本:
*/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
测试成功,大功告成!