首页 > 代码库 > 朋友,我用python给你发了一封邮件

朋友,我用python给你发了一封邮件

— 1. Start —

在某个周末,心血来潮,我想给我远方的朋友发送电子邮件,跟他分享我要在CSDN开设顺哥读源码的专栏。于是我登陆新浪邮箱,写下这样的内容:
技术分享
鼠标轻击“发送”按钮,我远在千里之外的朋友就可以看到我给他写的邮件了
沿着这个思路YY下去,我要怎么才能让我的朋友知道我完成了新的博客呢?每次写完都像上面这样写邮件告诉他?要是朋友比较多呢?那不是忙死顺哥啊。要是能够在每次更新博客之后自动发送邮件通知朋友是不是很好?
我拿出工作电脑开始翻看以前写过的发送告警邮件的代码,python真是一门简单到爆的编程语言,发送邮件只需要几行关键代码。如果你也想跟我一样通过python给朋友发送邮件,你首先需要一台电脑,电脑上还需要安装了python,然后你需要注册一个邮箱地址,下面是我的开发环境:

主题 限制
python版本 2.7.5
操作系统 windows7
依赖 smtplib
邮件服务器 smtp.sina.com

除了上面的开发环境外,我们还需要做一些准备工作,比如申请邮箱地址、想好邮件主题、邮件正文等,就像下面这样

主题 描述 是否必需
邮箱地址 电子邮件网络中的身份标识,本文将使用的邮箱地址:cug_heshun@sina.com
邮箱密码 邮箱地址访问邮件服务器时的密码,本文使用密码:**********(可以猜猜是什么哦)
收件人列表 邮件接收人的列表(一个或者多个邮箱地址),本文使用:anys_test@sina.com,60550295@qq.com
抄送列表 邮件抄送列表(一般抄送给那些需要知道邮件所述内容但不需要做任何事的人)
邮件主题 邮件所描述内容的概括,本文使用:“顺哥读源码”
邮件正文 邮件的主题部分内容,本文使用:“我亲爱的朋友:我打算在CSDN开设“顺哥读源码”的专栏,欢迎前来我的地盘留下你宝贵的意见,我们一起成长!”
邮件附件 以文件的形式(word文档、excel表格、图片、视频等)添加到邮件后面,严格来讲属于邮件正文的一部分

顺哥是个懒惰的人,为了减少输入,我们先把需要的信息保存在变量,就像下面这样:

# encoding: utf-8
import smtplib

smtp_server_addr = ‘smtp.sina.com‘

email_address = ‘cug_heshun@sina.com‘
email_password = ‘**********‘
send_to_list = [‘605502954@qq.com‘, ‘anys_test@sina.com‘]
subject = u"顺哥读源码"
message = u"""
我亲爱的朋友:
   我打算在CSDN开设“顺哥读源码”的专栏,欢迎前来我的地盘留下你宝贵的意见,我们一起成长!
"""

— 2. Send Mail —

准备工作到这里就算完成了,让我们来编写发送邮件的代码,编写完成之后可能是这样的:

# encoding: utf-8
import smtplib

smtp_server_addr = ‘smtp.sina.com‘

email_address = ‘cug_heshun@sina.com‘
email_password = ‘**********‘
send_to_list = [‘605502954@qq.com‘, ‘anys_test@sina.com‘]
subject = u"顺哥读源码"
message = u"""
我亲爱的朋友:
   我打算在CSDN开设“顺哥读源码”的专栏,欢迎前来我的地盘留下你宝贵的意见,我们一起成长!
"""


if __name__ == ‘__main__‘:
    smtp_server = smtplib.SMTP(smtp_server_addr)
    smtp_server.login(email_address, email_password)
    smtp_server.sendmail(email_address, send_to_list, message)

与之前相比,添加了三行代码:

  1. smtp_server = smtplib.SMTP(smtp_server_addr) ,创建连接到smtp_server_addr的连接,有很多个参数,完整的定义如下:smtplib.SMTP([host[, port[, local_hostname[, timeout]]]]),如果指定了host则实例化时连接到服务器,此时使用第二个参数指定的port或者默认的端口:25.如果未指定需要在登录服务器前调用SMTP.connect([host[, port]])来建立连接
  2. smtp_server.login(email_address, email_password),登录。要通过邮件服务器发送邮件,必须先登录认证通过
  3. smtp_server.sendmail(email_address, send_to_list, message),发送邮件。完整定义如下:SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])

— 3. UnicodeEncodeError —

激动吗?我要成功了,我可以通过python给我的朋友发送邮件了,好,让我们运行一下:

send: u‘\r\n\u6211\u4eb2\u7231\u7684\u670b\u53cb\uff1a\r\n   \u6211\u6253\u7b97\u5728CSDN\u5f00\u8bbe\u201c\u987a\u54e5\u8bfb\u6e90\u7801\u201d\u7684\u4e13\u680f\uff0c\u6b22\u8fce\u524d\u6765\u6211\u7684\u5730\u76d8\u7559\u4e0b\u4f60\u5b9d\u8d35\u7684\u610f\u89c1\uff0c\u6211\u4eec\u4e00\u8d77\u6210\u957f\uff01\r\n.\r\n‘
Traceback (most recent call last):
  File "E:/workspace/Demo/smtp_send_mail/send_mail.py", line 20, in <module>
    smtp_server.sendmail(email_address, send_to_list, message)
  File "C:\Python27\lib\smtplib.py", line 736, in sendmail
    (code, resp) = self.data(msg)
  File "C:\Python27\lib\smtplib.py", line 503, in data
    self.send(q)
  File "C:\Python27\lib\smtplib.py", line 323, in send
    self.sock.sendall(str)
  File "C:\Python27\lib\socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 2-8: ordinal not in range(128)

这是什么鬼?为什么他不能正常工作?看错误信息应该是编码问题,查阅相关资料之后发现,我们需要使用email这个python内置的模块来完成邮件信息的组织,下面是改善后的版本:

# encoding: utf-8
from email.mime import text
import smtplib

smtp_server_addr = ‘smtp.sina.com‘

email_address = ‘cug_heshun@sina.com‘
email_password = ‘**********‘
send_to_list = [‘605502954@qq.com‘, ‘anys_test@sina.com‘]
subject = u"顺哥读源码"
message = u"""
我亲爱的朋友:
   我打算在CSDN开设“顺哥读源码”的专栏,欢迎前来我的地盘留下你宝贵的意见,我们一起成长!
"""


if __name__ == ‘__main__‘:
    msg = text.MIMEText(message, ‘plain‘, ‘utf-8‘)
    smtp_server = smtplib.SMTP(smtp_server_addr)
    smtp_server.login(email_address, email_password)
    smtp_server.sendmail(email_address, send_to_list, msg.as_string())

我们from email.mime import text,使用msg = text.MIMEText(message, ‘plain‘, ‘utf-8‘)来构造邮件正文,在发送时先通过msg.as_string()将其转换为字符串。好,这样应该可以了吧,我们再试一下:

C:\Python27\python.exe E:/workspace/Demo/smtp_send_mail/send_mail.py

Process finished with exit code 0

哇,没报错,这是成功了吗?我好激动,让我们看看‘605502954@qq.com‘, ‘anys_test@sina.com‘有没有收到邮件
技术分享
技术分享

— 4. Humanize —

邮件是收到了,但似乎有一些不好的地方:

  • 邮件没有主题
  • 没有发件人

我们对代码做进一步的修改,为邮件添加主题和发件人

# encoding: utf-8
from email.header import Header
from email.mime import text
from email.utils import parseaddr, formataddr
import smtplib

smtp_server_addr = ‘smtp.sina.com‘

email_address = ‘cug_heshun@sina.com‘
email_password = ‘**********‘
send_to_list = [‘605502954@qq.com‘, ‘anys_test@sina.com‘]
subject = u"顺哥读源码"
message = u"""
我亲爱的朋友:
   我打算在CSDN开设“顺哥读源码”的专栏,欢迎前来我的地盘留下你宝贵的意见,我们一起成长!
"""


if __name__ == ‘__main__‘:
    msg = text.MIMEText(message, ‘plain‘, ‘utf-8‘)
    msg[‘From‘] = formataddr((Header(u‘顺哥‘, ‘utf-8‘).encode(), email_address))
    msg[‘Subject‘] = Header(subject, ‘utf-8‘).encode()
    smtp_server = smtplib.SMTP(smtp_server_addr)
    smtp_server.login(email_address, email_password)
    smtp_server.sendmail(email_address, send_to_list, msg.as_string())

新添加了下面的两行:

msg[‘From‘] = formataddr((Header(u‘顺哥‘, ‘utf-8‘).encode(), email_address))
msg[‘Subject‘] = Header(subject, ‘utf-8‘).encode()

去吧,孩子,看看你的成果:
技术分享
技术分享

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    朋友,我用python给你发了一封邮件