接单日记SMTP发送邮件

Posted A-L-Kun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了接单日记SMTP发送邮件相关的知识,希望对你有一定的参考价值。

接单日记(二)SMTP发送邮件

此为一个实验报告,故遵守实验报告的格式。

一、 实验目的

  1. 熟悉SMTP发送邮件的原理
  2. 使用SMTP实现自动化发送邮件的功能
  3. 熟练在实际场景中使用装饰器,提高代码的封装性
  4. 理解__name__在程序的作用

二、 实验内容

在QQ邮箱获取smtp服务器密钥,完成自动发送邮件的程序,要求:需要用到装饰器来进行smtp服务器的登录。

三、 程序及结果

1、 运行程序

from smtplib import SMTP
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr
from functools import wraps

receivers = [\'test@qq.com\', ]
subject = \'测试邮件\'


def decorate(fun_):
    username = \'?\'
    password_pass = \'?\'
    smtp = SMTP(\'smtp.qq.com\')
    smtp.login(username, password_pass)

    @wraps(fun_)
    def func_mail(*args, **kwargs):
        fun_(smtp, username, *args, **kwargs)
        smtp.quit()
        smtp.close()

    return func_mail


@decorate
def mail(smtp, username):
    for receiver_ in receivers:
        content = "这是一个测试邮件,不要回复哦~~~"
        msgRoot = MIMEText(content, "html",
                           "utf-8")
        msgRoot["Subject"] = Header(subject, "utf-8")
        msgRoot[\'From\'] = formataddr(("test", username))
        msgRoot[\'To\'] = formataddr((receiver_.split("@")[0], receiver_))
        smtp.sendmail(username, receiver_, msgRoot.as_string())
        print(receiver_, f\':发送完成, 发送内容为:content\')


if __name__ == \'__main__\':
    mail()

2、 运行结果

参考文章:https://www.cnblogs.com/liuzhongkun/p/16263523.html

利用Python的smtplib和email发送邮件

原理

网上已经有了很多的教程讲解相关的发送邮件的原理,在这里还是推荐一下廖雪峰老师的Python教程,讲解通俗易懂。简要来说,SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。而python内置的email模块则是负责邮件的内容、发送方、接收方等内容;具体的操作可以看代码。

而构造一个邮件对象就是一个Messag对象,如果构造一个MIMEText对象,就表示一个文本邮件对象,如果构造一个MIMEImage对象,就表示一个作为附件的图片,要把多个对象组合起来,就用MIMEMultipart对象,而MIMEBase可以表示任何对象。他们的嵌套关系如下:

Message
+- MIMEBase
   +- MIMEMultipart
   +- MIMENonMultipart
      +- MIMEMessage
      +- MIMEText
      +- MIMEImage

一些错误的总结

[1]提示smtplib.SMTPAuthenticationError: (550, b‘User has no permission‘)
这是因为邮箱没有开启客户端授权,邮箱这边的SMTP服务运行不起来;而现在基本所有的邮件都是需要客户端授权的,这里需要注意一下。解决办法为:进入163邮箱-设置-客户端授权密码-开启(授权码是用于登录第三方邮件客户端的专用密码),非第三方登录密码不变。
[2]提示smtplib.SMTPAuthenticationError: (535, b‘Error: authentication failed‘)
 以163邮箱为例,在开启POP3/SMTP服务,并开启客户端授权密码时会设置授权码,将这个授权码代替smtplib.SMTP().login(user,password)方法中的password即可。就是说你代码中的password为你所设置的授权码。
[3]提示554
说明邮件内容缺少信息,在现在的邮箱里一般有些内容需要填写。

代码

# 发送文本
# -*- coding: utf-8 -*-

from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
import smtplib

def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

from_addr = input('From: ')
password = input('Password: ')
to_addr = input('To: ')
smtp_server = input('SMTP server: ')

# 发的内容
msg = MIMEText('hello, send by Python...', 'plain', 'utf-8')
# 发件人
msg['From'] = _format_addr(u'Python爱好者 <%s>' % from_addr)
# 收件人
msg['To'] = _format_addr(u'管理员 <%s>' % to_addr)
# 标题
msg['Subject'] = Header(u'来自SMTP的问候……', 'utf-8').encode()

server = smtplib.SMTP(smtp_server, 25)
server.set_debuglevel(1)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()
# 发送附件
# -*- coding: utf-8 -*-

from email import encoders
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.utils import parseaddr, formataddr
import smtplib

def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

from_addr = input('From: ')
password = input('Password: ')
to_addr = input('To: ')
smtp_server = input('SMTP server: ')

# 邮件对象:
msg = MIMEMultipart()
msg['From'] = _format_addr(u'Python爱好者 <%s>' % from_addr)
msg['To'] = _format_addr(u'管理员 <%s>' % to_addr)
msg['Subject'] = Header(u'来自SMTP的问候……', 'utf-8').encode()

# 邮件正文是MIMEText:
msg.attach(MIMEText('send with file...', 'plain', 'utf-8'))

# 添加附件就是加上一个MIMEBase,从本地读取一个图片:
with open('e:/141.m4a', 'rb') as f:
    # 设置附件的MIME和文件名,这里是音乐类型:
    mime = MIMEBase('image', 'm4a', filename='141.m4a')
    # 加上必要的头信息:
    mime.add_header('Content-Disposition', 'attachment', filename='141.m4a')
    mime.add_header('Content-ID', '<0>')
    mime.add_header('X-Attachment-Id', '0')
    # 把附件的内容读进来:
    mime.set_payload(f.read())
    # 用Base64编码:
    encoders.encode_base64(mime)
    # 添加到MIMEMultipart:
    msg.attach(mime)

server = smtplib.SMTP(smtp_server, 25)
server.set_debuglevel(1)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()

代码经笔者都测试过,应该是没问题的。遇到错误看看是不是客户端的授权问题,或者是python的版本的问题。

以上是关于接单日记SMTP发送邮件的主要内容,如果未能解决你的问题,请参考以下文章

接单日记:理解浮点数运算的误差

接单日记文本处理之词云生成

linux PHPMailer 发送邮件sendmail 发邮件失败问题

Spring Boot 2.x 实践记:Mail

Spring Boot 2.x 实践记:Mail

Spring Boot 2.x 实践记:Mail