返回总目录页

smtplib详解,发送邮件

创建邮箱账号

1、官网登录邮箱。

2、在邮箱的主界面找到“设置”,新版的主界面与旧版稍有不同,一般位于上方,齿轮状的即是。

3、点击齿轮状的设置标志,会弹出一个下拉菜单,在最后有我们找的关于邮箱的更多设置,点击进入。

 

 

4、此时切换到了设置面板,在设置区我们需要切换至账户界面,因为一般情况下pop3和smtp服务都是在这里设置的。

5、继续把网页往下拉,下面出现了我们要找的pop3和smtp服务设置。默认状态下显示为关闭。此时我们需要开启它,只需要点击开启就行了,然后点击保存。

6、填入验证码,保存设置成功。

 

 

新浪邮箱怎么不能用邮件客户端登陆了?

需要开启IMAP服务:

1、先登录自己的sina邮箱。

2、 单击窗口上的 "设置" 连接,进入到"邮箱设置"中,,切换到"账户"标签页,选中下方的开启“IMAP/SMTP”这时它的附加选项被激活,最后点击"保存更改"即可

 

发送邮件程序1

import smtplib
server = "smtp.sina.com"
fromaddr= "dachxxxx@sina.com" #须修改
toaddr = "8xxxx@qq.com" #须修改
msg = """
to:%s
from:%s
Hello,I am smtp server
""" %(toaddr,fromaddr)
s = smtplib.SMTP(server)
s.set_debuglevel(1)
s.login("dachxxx@sina.com","1535d05c76ca6xxx")#须修改
s.sendmail(fromaddr,toaddr,msg)
程序

 

 

 发送邮件程序2

参考:https://docs.python.org/2/library/email-examples.html

官网的缺少一个登陆认证,没有的话报错认证啥问题的

# Import smtplib for the actual sending function
import smtplib

# Import the email modules we'll need
from email.mime.text import MIMEText

# Open a plain text file for reading.  For this example, assume that
# the text file contains only ASCII characters.
fp = open('textfile', 'r',encoding='utf-8')
# Create a text/plain message
msg = MIMEText(fp.read())
fp.close()

# me == the sender's email address
# you == the recipient's email address
msg['Subject'] = 'The contents of %s' %("mcw")
msg['From'] = 'dacxxx@sina.com'
msg['To'] = '8xxxx@qq.com'

# Send the message via our own SMTP server, but don't include the
# envelope header.
s = smtplib.SMTP('smtp.sina.com')
s.login("dacxxxi@sina.com","1535d05c76ca6xxx")
s.sendmail('dacxxx@sina.com', '8xxx@qq.com', msg.as_string())
s.quit()
程序

结果:

 

 

解析HTML,需要添加html参数。

 

 邮件模板

 

import smtplib

# Import the email modules we'll need
from email.mime.text import MIMEText

# Open a plain text file for reading.  For this example, assume that
# the text file contains only ASCII characters.
fp = open(r'templates/youjian.html', 'r',encoding='utf-8')
# Create a text/plain message
msg = MIMEText(fp.read(),'html')
fp.close()

# me == the sender's email address
# you == the recipient's email address
msg['Subject'] = 'The contents of %s' %("mcw")
msg['From'] = 'dxx@sina.com'
msg['To'] = '8xx@qq.com'

# Send the message via our own SMTP server, but don't include the
# envelope header.
s = smtplib.SMTP('smtp.sina.com')
s.login("dxxi@sina.com","15xx")
s.sendmail('daxx@sina.com', '8xx@qq.com', msg.as_string())
s.quit()
邮件程序

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>邮件提醒</title>   
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <!--<script type="text/javascript">-->
    <!--// var para = function () {--> <!--// }--> <!--var url = document.location.toString();-->
    <!--var arrUrl = url.split("?");--> <!--var para = arrUrl[1];--> <!--alert('===='+url);--> <!--</script>--> </head>
<body style="margin: 0; padding: 0;">
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse: collapse;">  
    <tr>
        <td>
            <div style="margin: 20px;text-align: center;margin-top: 50px"><img
                    src="mcw.jpg" border="0"
                    style="display:block;width: 100%;height: 100%"></div>
        </td>
    </tr>
    <tr>
        <td>
            <div style="border: #36649d 1px dashed;margin: 30px;padding: 20px"><label
                    style="font-size: 22px;color: #36649d;font-weight: bold">恭喜您,注册成功!</label>
                <p style="font-size: 16px">亲爱的&nbsp;<label style="font-weight: bold"> XXX先生/女士</label>&nbsp; 您好!欢迎加入xxx。
                </p>
                <p style="font-size: 16px">您已于2022年9月23日充值成功,希望更好的为您服务!</p></div>
        </td>
    </tr>
     
    <tr>
        <td>
            <div style="margin: 40px"><p style="font-size: 16px">xxx管理团队</p>
                <p style="color:red;font-size: 14px ">(这是一封自动发送的邮件,请勿回复。)</p></div>
        </td>
    </tr>

    <tr>
        <td>
            <div align="right" style="margin: 40px;border-top: solid 1px gray" id="bottomTime"><p
                    style="margin-right: 20px">xxx科技有限公司</p> <label style="margin-right: 20px">2018年08月30日</label></div>
        </td>
    </tr>
</table>
</body>
</html>
邮件模板

使用jinja2定义自己的邮件html模板并发送邮件。

 模板渲染和源码邮件发送代码如下:

import smtplib
from email.mime.text import MIMEText
from jinja2 import PackageLoader, Environment, FileSystemLoader
dic={
    "10.0.0.11":{"host":"10.0.0.11","hostname":"mcw01","mem":"20%"},
    "10.0.0.12":{"host":"10.0.0.12","hostname":"mcw02","mem":"60%"},
    "10.0.0.13":{"host":"10.0.0.13","hostname":"mcw03","mem":"55%"}
}

path_dir = r'C:\mcw\testt\templates\\'    #模板文件所在的绝对路径
loader = FileSystemLoader(searchpath=path_dir)
env = Environment(loader=loader)
template = env.get_template("jinja2研究.html") # 第一步将模板文件放到这里
buf = template.render(dic=dic,) #第二步将模板文件中用来渲染的数据传进去。用变量接收渲染后的html页面源码
# with open(os.path.join(path_dir, "jinja2xxx.html"), "w" ) as fp:  #可以将buf模板渲染后的数据重新写入另一个文件
#   fp.write(buf)   #这里重新写入文件的时候,中文会出现乱码

####################上面是jinja2渲染模板,下面是将渲染后源码发送邮件出去######################################


msg = MIMEText(buf,'html')  #似乎是加密后的数据。指明是html格式,将渲染后的页面源码buf传进去,作为消息页面展示
                    #我们将需要的数据已经渲染进来消息里面了

msg['Subject'] = 'The contents of %s' %("mcw")
msg['From'] = 'dxx@sina.com'
msg['To'] = '8xx@qq.com'

s = smtplib.SMTP('smtp.sina.com')
s.login("dxx@sina.com","1xx")
s.sendmail('dxx@sina.com', '8xx@qq.com', msg.as_string())
s.quit()

下面是模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body >
<div style="background-color: blue;width: 500px;height: 400px">
<table border="1" cellspacing="0" style="height: 150px;width: 100%">
    <thead>
    <tr style="background-color: gold;">
        <th>主机ip</th>
        <th>主机名</th>
        <th>内存使用率</th>
    </tr>
    </thead>
    <tbody>
    {% for k,foo in dic.items() %}
        <tr style="background-color: gold;">
            <td>{{ foo.host }}</td>
            <td>{{ foo.hostname }}</td>
            <td>{{ foo.mem }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>
</div>
 
</body>
</html>

效果如下:执行程序后,模板渲染,然后渲染后的buf源码放到邮件的消息中,做邮件发送。我们还可以将渲染后的页面保存到另一个文件,但是保存会出现中文乱码。应该以wb的方式写入,或许就可以了把,或者直接wb方式写,是否需要编码后放进去呢?

 如下,看着还是不错的,我们需要改改样式,改漂亮些。可以用来发送运维邮件通知等的。需要思考的是,图片和附件是如何加入到邮件中。这里的jinja2应该也是可以使用模板继承的方式去写的吧,不知道可不可以加入js。应该也是可以的吧

 发送,抄送邮件并带上附件的函数

一个附件

效果如下:

程序如下:

#1.导包
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import logging

#2.定义发送邮件函数


def send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name):
    message = MIMEMultipart()
    message['From'] = MAIL_USERNAME  # 发件人
    message['To'] = ";".join(accept_list)  # 收件人,将列表转换为字符串
    message["Cc"] = ";".join(Cc_list)  # 抄送人,将列表转换为字符串
    message['Subject'] = SUBJECT  # 邮件主题
    message.attach(MIMEText(text, 'plain', 'utf-8'))  # 格式化邮件内容,编码为utf-8

    att1 = MIMEText(open(file_name, 'rb').read(), 'base64', 'utf-8')  # 添加附件
    att1["Content-Type"] = 'application/octet-stream'  # 设置类型
    att1["Content-Disposition"] = 'attachment; filename="{0}"'.format("test.xlsx")  # 设置邮件用现实的名称,这里是格式化filename也就是邮件附件使用名称
    message.attach(att1)

    try:
        mailServer = smtplib.SMTP(MAIL_SERVER, 25)  # 25为端口号(邮件)
        # 登录邮箱
        mailServer.login(MAIL_USERNAME, MAIL_PASSWORD)  # 需要的是,邮箱的地址和授权密码
        # 发送文件
        mailServer.sendmail(MAIL_USERNAME, accept_list + Cc_list, message.as_string())
        mailServer.close()  # 关闭连接
        return True
    except Exception as e:
        # logging.debug(e)
        print(e)
        return False


#3.调用发送邮件函数


def main():
    MAIL_SERVER = 'smtp.sina.com'  # smtp服务器
    MAIL_USERNAME = 'dxx@sina.com'  # 发件人
    MAIL_PASSWORD = '1xxx'  # 发送者授权码
    accept_list = ['89xx@qq.com',]  # 收件人
    Cc_list = ['89xx5@qq.com', '28xx@qq.com']  # 抄送人
    SUBJECT = "我是邮件主题"  # 主题
    text = "邮件内容吗?"  # 内容
    file_name = r"C:\mcw\testt\templates\youjian.html"  # 上传附件名称(当前路径)

    if send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name):
        logging.debug("Send mail succed!")

    else:
        logging.debug("Send mail failed")


if __name__ == '__main__':
    main()

我们预览一下附件

就是我们的html页面

我再加一个附件。多个附件

 如下,是多个附件的效果..第二个附件能看出是个图片了。如果是py程序,不支持查看

需要在main函数下添加第二个附件,加到发送函数的调用参数中
file_name2 = r"C:\mcw\testt\templates\mcw.jpg" # 上传附件名称(当前路径)

if send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name1,file_name2):


需要在发送函数定义中接收第二个附件的接收参数
def send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name1,file_name2):

需要在发送函数体中定义这个附件,添加设置属性,样子是一样的。只是把文件名字都换成第二个文件的就行
att2 = MIMEText(open(file_name2, 'rb').read(), 'base64', 'utf-8') # 添加附件
att2["Content-Type"] = 'application/octet-stream' # 设置类型
att2["Content-Disposition"] = 'attachment; filename="{0}"'.format(file_name2) # 设置邮件用现实的名称
message.attach(att2)

 下面是比较完美的邮件。发送抄送附件以及html美化邮件内容

 

 

 

from jinja2 import PackageLoader, Environment, FileSystemLoader
dic={
    "10.0.0.11":{"host":"10.0.0.11","hostname":"mcw01","mem":"20%"},
    "10.0.0.12":{"host":"10.0.0.12","hostname":"mcw02","mem":"60%"},
    "10.0.0.13":{"host":"10.0.0.13","hostname":"mcw03","mem":"55%"}
}

path_dir = r'C:\mcw\testt\templates\\'    #模板文件所在的绝对路径
loader = FileSystemLoader(searchpath=path_dir)
env = Environment(loader=loader)
template = env.get_template("jinja2研究.html") # 第一步将模板文件放到这里
buf = template.render(dic=dic,) #第二步将模板文件中用来渲染的数据传进去。用变量接收渲染后的html页面源码
# with open(os.path.join(path_dir, "jinja2xxx.html"), "w" ) as fp:  #可以将buf模板渲染后的数据重新写入另一个文件
#   fp.write(buf)   #这里重新写入文件的时候,中文会出现乱码
print(buf)


#1.导包
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import logging

#2.定义发送邮件函数


def send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name):
    message = MIMEMultipart()
    message['From'] = MAIL_USERNAME  # 发件人
    message['To'] = ";".join(accept_list)  # 收件人,将列表转换为字符串
    message["Cc"] = ";".join(Cc_list)  # 抄送人,将列表转换为字符串
    message['Subject'] = SUBJECT  # 邮件主题
    message.attach(MIMEText(text, 'html', 'utf-8'))  # 格式化邮件内容,编码为utf-8.修改格式为html

    att1 = MIMEText(open(file_name, 'rb').read(), 'base64', 'utf-8')  # 添加附件
    att1["Content-Type"] = 'application/octet-stream'  # 设置类型
    att1["Content-Disposition"] = 'attachment; filename="{0}"'.format('test.xlsx')  # 设置附件用现实的名称
    message.attach(att1)


    try:
        mailServer = smtplib.SMTP(MAIL_SERVER, 25)  # 25为端口号(邮件)
        # 登录邮箱
        mailServer.login(MAIL_USERNAME, MAIL_PASSWORD)  # 需要的是,邮箱的地址和授权密码
        # 发送文件
        mailServer.sendmail(MAIL_USERNAME, accept_list + Cc_list, message.as_string())
        mailServer.close()  # 关闭连接
        return True
    except Exception as e:
        # logging.debug(e)
        print(e)
        return False


#3.调用发送邮件函数


def main():
    MAIL_SERVER = 'smtp.sina.com'  # smtp服务器
    MAIL_USERNAME = 'dxx@sina.com'  # 发件人
    MAIL_PASSWORD = '15xx'  # 发送者授权码
    accept_list = ['8xx@qq.com',]  # 收件人
    Cc_list = ['8xx@qq.com', '28x@qq.com']  # 抄送人
    SUBJECT = "我是邮件主题"  # 主题也是标题
    text = buf  # 内容
    file_name = r"C:\mcw\testt\templates\youjian.html"  # 上传附件名称(当前路径)

    if send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name):
        logging.debug("Send mail succed!")

    else:
        logging.debug("Send mail failed")


if __name__ == '__main__':
    main()

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body >
<div style="background-color: blue;width: 500px;height: 200px">
<table border="1" cellspacing="0" style="height: 150px;width: 100%">
    <thead>
    <tr style="background-color: gold;">
        <th>主机ip</th>
        <th>主机名</th>
        <th>内存使用率</th>
    </tr>
    </thead>
    <tbody>
    {% for k,foo in dic.items() %}
        <tr style="background-color: gold;">
            <td>{{ foo.host }}</td>
            <td>{{ foo.hostname }}</td>
            <td>{{ foo.mem }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>
</div>
 
</body>
</html>

 邮件内容带图片,成功半步,可能是邮箱不支持把

1、将图片编码,转成字符串把编码后的b''去掉

import base64
img_file = open(r'C:\mcw\testt\templates\mcw.jpg', 'rb')
base64_data = str(base64.b64encode(img_file.read())).rstrip("'").lstrip("b'")

 2、将编码后的字符串渲染到html页面中

html页面中调用:

<img src="data:image/png;base64,{{ base64_data }}" alt="image1" style="height: 200px;width: 100%">

 python程序将字符串传进模板

buf = template.render(dic=dic,base64_data=base64_data) #第二步将模板文件中用来渲染的数据传进去。用变量接收渲染后的html页面源码

3、将html源码传给邮件的内容中,html格式

4、把源码保存下来自己访问效果:

图片是有的

 

 把html数据发送给邮件的效果:

读不出来图片

 

 

import os
from jinja2 import PackageLoader, Environment, FileSystemLoader
dic={
    "10.0.0.11":{"host":"10.0.0.11","hostname":"mcw01","mem":"20%"},
    "10.0.0.12":{"host":"10.0.0.12","hostname":"mcw02","mem":"60%"},
    "10.0.0.13":{"host":"10.0.0.13","hostname":"mcw03","mem":"55%"}
}
import base64
img_file = open(r'C:\mcw\testt\templates\mcw.jpg', 'rb')
base64_data = str(base64.b64encode(img_file.read())).rstrip("'").lstrip("b'")

path_dir = r'C:\mcw\testt\templates\\'    #模板文件所在的绝对路径
loader = FileSystemLoader(searchpath=path_dir)
env = Environment(loader=loader)
template = env.get_template("jinja2研究.html") # 第一步将模板文件放到这里
buf = template.render(dic=dic,base64_data=base64_data) #第二步将模板文件中用来渲染的数据传进去。用变量接收渲染后的html页面源码
with open(os.path.join(path_dir, "jinja2xxx.html"), "w" ) as fp:  #可以将buf模板渲染后的数据重新写入另一个文件
  fp.write(buf)   #这里重新写入文件的时候,中文会出现乱码
print(buf)


# img_file = open(r'C:\mcw\testt\templates\mcw.jpg', 'rb')
# base64_data = str(base64.b64encode(img_file.read()))
# buf = buf % (base64_data)
#
#1.导包
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import logging
from email.mime.image import MIMEImage

#2.定义发送邮件函数


def send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name):
    message = MIMEMultipart('related') # 邮件类型,如果要加图片等附件,就得是这个
    message['From'] = MAIL_USERNAME  # 发件人
    message['To'] = ";".join(accept_list)  # 收件人,将列表转换为字符串
    message["Cc"] = ";".join(Cc_list)  # 抄送人,将列表转换为字符串
    message['Subject'] = SUBJECT  # 邮件主题

    # import base64
    # img_file = open(r'C:\mcw\testt\templates\mcw.jpg', 'rb')
    # base64_data = str(base64.b64encode(img_file.read()))
    # text = text % (base64_data)
    # print(text)
    # return
    message.attach(MIMEText(text, 'html', 'utf-8'))  # 格式化邮件内容,编码为utf-8.修改格式为html

    att1 = MIMEText(open(file_name, 'rb').read(), 'base64', 'utf-8')  # 添加附件
    att1["Content-Type"] = 'application/octet-stream'  # 设置类型
    att1["Content-Disposition"] = 'attachment; filename="{0}"'.format('test.xlsx')  # 设置附件用现实的名称
    message.attach(att1)

    # fp = open(r'C:\mcw\testt\templates\mcw.jpg', 'rb')
    # msgImage = MIMEImage(fp.read())
    # fp.close()
    # msgImage.add_header('Content-ID', 'image1')  # 这个id用于上面html获取图片
    # message.attach(msgImage)

    try:
        mailServer = smtplib.SMTP(MAIL_SERVER, 25)  # 25为端口号(邮件)
        # 登录邮箱
        mailServer.login(MAIL_USERNAME, MAIL_PASSWORD)  # 需要的是,邮箱的地址和授权密码
        # 发送文件
        mailServer.sendmail(MAIL_USERNAME, accept_list + Cc_list, message.as_string())
        mailServer.close()  # 关闭连接
        return True
    except Exception as e:
        # logging.debug(e)
        print(e)
        return False


#3.调用发送邮件函数


def main():
    MAIL_SERVER = 'smtp.sina.com'  # smtp服务器
    MAIL_USERNAME = 'daxx@sina.com'  # 发件人
    MAIL_PASSWORD = '15xx'  # 发送者授权码
    accept_list = ['8xx@qq.com',]  # 收件人
    Cc_list = ['8xx@qq.com', '2xx@qq.com']  # 抄送人
    SUBJECT = "我是邮件主题"  # 主题也是标题
    text = buf  # 内容
    file_name = r"C:\mcw\testt\templates\youjian.html"  # 上传附件名称(当前路径)

    if send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name):
        logging.debug("Send mail succed!")

    else:
        logging.debug("Send mail failed")


if __name__ == '__main__':
    main()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body >
<div style=";width: 500px;height: 200px">
<table border="1" cellspacing="0" style="height: 150px;width: 100%">
    <thead>
    <tr style="">
        <th>主机ip</th>
        <th>主机名</th>
        <th>内存使用率</th>
    </tr>
    </thead>
    <tbody>
    {% for k,foo in dic.items() %}
        <tr style="">
            <td>{{ foo.host }}</td>
            <td>{{ foo.hostname }}</td>
            <td>{{ foo.mem }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>
    <img src="data:image/png;base64,{{ base64_data }}" alt="image1" style="height: 200px;width: 100%">
</div>
 
</body>
</html>

 我手动把图片编码复制上去,是能显示的

 

 貌似邮箱会把我们的字符串替换掉,导致无法访问图片,如下,真实访问是到的是这样的,我们加载进邮件消息对象之前是有图片编码的,那么问题可能是出在加载进图片对象时把这个编码字符串弄丢了,或者是邮箱服务器给我们替换掉了,显然跟html同为字符串,加载进消息对象时弄丢的可能性不大。

 

 

 

 

 

参考链接:https://vimsky.com/zh-tw/examples/detail/python-method-smtplib.SMTPSenderRefused.html

posted @ 2021-12-28 01:54  马昌伟  阅读(561)  评论(0编辑  收藏  举报
博主链接地址:https://www.cnblogs.com/machangwei-8/