准备工作
开启QQ邮箱的SMTP协议,按照指引操作,然后就能获取授权码,记下来。
这段代码实现了使用 Python 发送电子邮件的功能,主要目的是向指定收件人发送包含特定内容的邮件。以下是对代码的详细润色和分析:
代码
# coding=utf-8
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
import os
# 设置发件人和收件人信息
SENDER_EMAIL = 'xxx@xx.com' # 自己邮箱
SENDER_PASSWORD = 'xxxxx' # 自己授权码
RECIPIENT_EMAIL = 'xxx@xx.com' # 自己邮箱(这是收件人,可填自己)
def send_mail(content):
"""
发送邮件的函数
:param content: 邮件正文内容
"""
msg = MIMEText(content, 'plain', 'utf-8')
msg['From'] = formataddr(["Jack", SENDER_EMAIL]) # 发件人邮箱昵称、发件人邮箱账号
msg['To'] = formataddr(["Rose", RECIPIENT_EMAIL]) # 收件人邮箱昵称、收件人邮箱账号
msg['Subject'] = "树莓派 IP 地址获取" # 邮件的主题
try:
server = smtplib.SMTP("smtp.qq.com", 587) # 发件人邮箱中的 SMTP 服务器,端口是 587
server.starttls() # 添加 TLS 加密
server.login(SENDER_EMAIL, SENDER_PASSWORD) # 登录发件人邮箱
server.sendmail(SENDER_EMAIL, [RECIPIENT_EMAIL], msg.as_string()) # 发送邮件
server.quit() # 关闭连接
print("发送邮件成功")
except smtplib.SMTPException as e:
print(f"发送邮件时发生 SMTP 相关错误: {e}")
except Exception as e:
print(f"发送邮件失败,原因: {e}")
def mail():
try:
# 获取 ifconfig 命令内容
# cmd = 'ifconfig'
# m = os.popen(cmd)
# content = m.read()
# m.close()
# 暂时使用测试内容
content = "this is a test!"
send_mail(content)
except Exception as e:
print(f"邮件发送过程中出现异常: {e}")
if __name__ == "__main__":
mail()
代码分析
-
导入模块:
import smtplib from email.mime.text import MIMEText from email.utils import formataddr import os
smtplib
:用于发送邮件的 SMTP 协议库。MIMEText
:用于创建邮件正文内容。formataddr
:用于格式化邮件的发件人和收件人信息。os
:用于与操作系统进行交互,这里原本可能用于执行系统命令获取树莓派 IP 地址,但代码中未实际使用。
-
设置发件人和收件人信息:
SENDER_EMAIL = 'xxx@xx.com' SENDER_PASSWORD = 'xxxxx' RECIPIENT_EMAIL = 'xxx@xx.com'
定义了发件人邮箱地址、发件人邮箱授权码以及收件人邮箱地址。建议将这些敏感信息进行妥善处理,比如从配置文件中读取,而不是直接硬编码在代码中。
-
定义
send_mail
函数:def send_mail(content): msg = MIMEText(content, 'plain', 'utf-8') msg['From'] = formataddr(["Jack", SENDER_EMAIL]) msg['To'] = formataddr(["Rose", RECIPIENT_EMAIL]) msg['Subject'] = "树莓派 IP 地址获取" try: server = smtplib.SMTP("smtp.qq.com", 587) server.starttls() server.login(SENDER_EMAIL, SENDER_PASSWORD) server.sendmail(SENDER_EMAIL, [RECIPIENT_EMAIL], msg.as_string()) server.quit() print("发送邮件成功") except smtplib.SMTPException as e: print(f"发送邮件时发生 SMTP 相关错误: {e}") except Exception as e: print(f"发送邮件失败,原因: {e}")
- 功能:该函数负责创建邮件内容并发送邮件。
- 参数:
content
为邮件正文内容。 - 实现步骤:
- 使用
MIMEText
创建邮件正文,设置内容为content
,格式为plain
(纯文本),编码为utf - 8
。 - 使用
formataddr
格式化发件人和收件人信息,分别设置发件人昵称为Jack
和收件人昵称为Rose
。 - 设置邮件主题为 “树莓派 IP 地址获取”。
- 尝试连接到 QQ 邮箱的 SMTP 服务器(
smtp.qq.com
),端口号为 587。添加server.starttls()
进行 TLS 加密,提高连接安全性。 - 使用发件人邮箱地址和授权码登录服务器。
- 发送邮件,将邮件内容转换为字符串形式进行发送。
- 关闭与服务器的连接。
- 打印发送成功的消息,如果发生
SMTPException
或其他异常,打印相应的错误信息。
- 使用
-
定义
mail
函数:def mail(): try: # 获取 ifconfig 命令内容 # cmd = 'ifconfig' # m = os.popen(cmd) # content = m.read() # m.close() # 暂时使用测试内容 content = "this is a test!" send_mail(content) except Exception as e: print(f"邮件发送过程中出现异常: {e}")
- 功能:该函数负责组织邮件内容并调用
send_mail
函数发送邮件。 - 实现步骤:
- 原本意图是通过执行
ifconfig
命令获取树莓派的 IP 地址作为邮件内容,但代码中这部分被注释掉了,暂时使用测试内容this is a test!
。 - 调用
send_mail
函数发送邮件,并捕获可能出现的异常,打印异常信息。
- 原本意图是通过执行
- 功能:该函数负责组织邮件内容并调用
-
主程序入口:
if __name__ == "__main__": mail()
程序的入口点,调用
mail
函数开始执行邮件发送流程。
存在问题与改进建议
- 硬编码问题:发件人邮箱、授权码和收件人邮箱等敏感信息硬编码在代码中,存在安全风险。建议将这些信息存储在配置文件中,并在运行时读取。
- 错误处理细化:虽然捕获了异常,但可以进一步细化错误处理。例如,针对不同的
SMTPException
错误码进行不同的处理,提供更详细的错误提示。 - 功能完整性:代码中获取树莓派 IP 地址的部分被注释掉了,若要实现完整功能,需要确保这部分代码的正确性和有效性。
- 日志记录:可以添加日志记录功能,将邮件发送的相关信息(如发送时间、是否成功、错误信息等)记录到日志文件中,方便调试和跟踪。
改进示例
配置文件 config.ini
[email]
sender_email = xxx@xx.com
sender_password = xxxxx
recipient_email = xxx@xx.com
Python 代码
# coding=utf-8
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
import os
import configparser
import logging
# 配置日志
logging.basicConfig(filename='email_sender.log', level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
def send_mail(sender_email, sender_password, recipient_email, content):
msg = MIMEText(content, 'plain', 'utf-8')
msg['From'] = formataddr(["Jack", sender_email])
msg['To'] = formataddr(["Rose", recipient_email])
msg['Subject'] = "树莓派 IP 地址获取"
try:
server = smtplib.SMTP("smtp.qq.com", 587)
server.starttls()
server.login(sender_email, sender_password)
server.sendmail(sender_email, [recipient_email], msg.as_string())
server.quit()
logging.info("邮件发送成功")
print("发送邮件成功")
except smtplib.SMTPException as e:
logging.error(f"发送邮件时发生 SMTP 相关错误: {e}")
print(f"发送邮件时发生 SMTP 相关错误: {e}")
except Exception as e:
logging.error(f"发送邮件失败,原因: {e}")
print(f"发送邮件失败,原因: {e}")
def get_ip_address():
try:
cmd = 'ifconfig'
m = os.popen(cmd)
content = m.read()
m.close()
return content
except Exception as e:
logging.error(f"获取 IP 地址时发生错误: {e}")
return "无法获取 IP 地址"
def mail():
config = configparser.ConfigParser()
config.read('config.ini')
sender_email = config.get('email','sender_email')
sender_password = config.get('email','sender_password')
recipient_email = config.get('email','recipient_email')
content = get_ip_address()
send_mail(sender_email, sender_password, recipient_email, content)
if __name__ == "__main__":
mail()
通过上述改进,将敏感信息存储在配置文件中,增强了安全性;细化了错误处理,并添加了日志记录功能,方便调试和维护;同时恢复了获取树莓派 IP 地址的功能。