Python32 发送邮件带附件 UnicodeEncodeError


这是我的第一个py脚本, 已经研究两天了, 不知道具体是什么问题.
One.py 获取一个网页中的文章, 然后保存到一个utf-8 编码的文件中.
Mail.py 发送一个带有附件的邮件

如果我分开执行两个脚本. 先执行 One.py 脚本,生成一个附件文件, 然后在控制台执行 Mail.py 传入One生成的附件文件路径, 它能成功发送邮件.
如果我在 One.py 中直接调用 Mail.py 中 SendMail() 方法传入附件发送邮件,就会报错 : UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-9: ordinal not in range(128) .

One.py


 # -*- coding: utf-8 -*-
# script for python3.2
import urllib.request,re,sys,os.path
import Mail

# 获取网页内容
def GetWebContent(url):
    return urllib.request.urlopen(url).read().decode("utf-8")

# 获取网页中文章的内容
def GetOntArticle():
    print(sys.getdefaultencoding())
    page = GetWebContent("http://www.wufazhuce.com")
    oneArticle = re.compile(r"one-articulo-titulo.*?</p>", re.DOTALL).findall(page)
    oneArticleLink = re.compile(r'http.*?\"', re.I).findall(oneArticle[0])[0]
    oneArticleLink = oneArticleLink[0:(len(oneArticleLink) - 1)]
    articleContent = GetWebContent(oneArticleLink)
    articleTitle = re.compile(r'articulo-titulo">.*?</h2>', re.DOTALL).findall(articleContent)[0]
    articleTitle = articleTitle[17:len(articleTitle[0]) - 6].expandtabs(0)
    # print(articleTitle)
    articleBody = re.compile(r'articulo-contenido">.*?</div>', re.DOTALL).findall(articleContent)[0]
    articleBody = articleBody[20:len(articleBody) - 6]
    # print(articleBody)
    articleFile = sys.path[0] + '\Article\Article.txt'
    # print(articleFile)
    # 写入文件, 稍后作为邮件的附件发送
    fileContent = open(articleFile, 'w+', encoding="utf-8")
    fileContent.write(articleBody)
    fileContent.close()
    # Mail.SendMail(articleTitle, articleFile)

if __name__ == '__main__':
    GetOntArticle()

Mail.py


 # -*- coding: utf-8 -*-
# script for python3.2
import os, sys
import smtplib
import mimetypes
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.audio import MIMEAudio
from email.mime.image import MIMEImage
from email.encoders import encode_base64

# 邮件帐号和密码
MAIL_QQ_USER = "[email protected]"
MAIL_QQ_PWD = "xxxx"
MAIL_QQ_HOST = "smtp.qq.com"

# 接受方邮件帐号
RECIPIENT = ["[email protected]"]
print(sys.getdefaultencoding())

class QMail():
    # 初始化
    def __init__(self, user, pwd, host):
        self.mail_user = user
        self.mail_pwd = pwd
        self.mail_server = smtplib.SMTP()
        self.mail_server.connect(host)
        self.mail_server.ehlo()
        self.mail_server.login(self.mail_user, self.mail_pwd)

    def __del__(self):
        self.mail_server.close()

    # 发送邮件
    def send_mail(self, recipient, subject, text, file_path):
        msg = MIMEMultipart()
        msg["From"] = self.mail_user
        msg["Subject"] = subject
        msg["To"] = ",".join(recipient)
        msg.attach(MIMEText(text))
        msg.attach(self.get_attachment(file_path))
        self.mail_server.sendmail(self.mail_user, recipient, msg.as_string())
        print("mail send")

    # 添加邮件附件
    def get_attachment(self, file_path):
        file_name = file_path.split("\\")[-1]
        attachment = MIMEText(open(file_path, 'rb').read(), 'base64', 'utf-8')
        attachment["Content-Type"] = 'application/octet-stream'
        attachment["Content-Disposition"] = 'attachment; filename=' + file_name
        print("read")
        return attachment

def SendMail(articleTitle, articleFile):
    mail = QMail(MAIL_QQ_USER, MAIL_QQ_PWD, MAIL_QQ_HOST)
    mail.send_mail(RECIPIENT, articleTitle, 'python Send To Kindle', articleFile)

if __name__ == '__main__':
    SendMail("send text mail",r"d:\PythonProjects\SendToKindle\Article\Article.txt")

python3.x mail

mmmmmmm 9 years, 9 months ago

.as_string() 改成 .as_bytes() 试试?不过一般邮件都是 8-bit clean 的。

不过你的邮件头没编码啊。email.header 模块开头有示例,如何编码非 ASCII 的邮件头。

忽然有一天 answered 9 years, 9 months ago

感谢 @依云 的回答和帮助. 问题确实出在邮件头. 第一次写python脚本, 遇到问题有人帮助还是很开心.
因为电子邮件旧标准中使用的是ASCII字符, 如果要向邮件头里面添加除ASCII以外的字符, 那么就需要先将中文字符进行转码操作. 所以在添加邮件标题的时候应该是这样才对:


 # 引用
from email.header import Header

        msg["Subject"] = Header(subject, "utf-8")

还需多学习.

LawRuru answered 9 years, 9 months ago

Your Answer