用Python收发电子邮件

匆匆过客 提交于 2020-02-19 10:20:23

image

电子邮件是最古老的互联网服务之一,发明于1969年,它已经50岁了!它并不要求收信人发信人同时连接网络,邮件存放于服务器,所以至今在企业内部还在大量使用。而且它是开放协议,没有被某大公司垄断。我们完全可以拿来做一个可靠的消息来源。

比如说我们在远程主机运行一个耗时较长的任务,或者搭建某个自己写的后台服务,当某些事件发生时,就可以发送一个邮件,手机任何一个邮件客户端都可以接收推送。

国内较好的邮件服务器就是QQ邮件了,它支持SMTP, ftjMAP, 默认都支持SSL的,这点很重要。要知道SMTP, POP密码都是明文显示在TCP包里。要开启SMTP/IMAP, 要在QQ邮件里做一下设置,拿到授权码,这个就是做为SMTP/IMAP的密码,而不是QQ密码。

image

image

image

用IMAP接收邮件

python标准库里的imaplib就支持IMAP, 连接imap.qq.com即可


with IMAP4_SSL("imap.qq.com") as M:

    M.noop()

    M.login("111111@qq.com", "gzoyimtltnqsbdba")  #qq邮件地址和刚才拿到的授权码,注意不是QQ号码和QQ密码

    M.select()
      typ, data = M.search(None, 'ALL')  #ALL为所有邮件,可替换为想搜索的字符串
    count = 10
    pcount = 1
    for num in data[0].split():
        typ, data = M.fetch(num, '(RFC822)')   #RFC822 为email标准
        for response_part in data:
            if isinstance(response_part, tuple):
                part = response_part[1].decode('utf-8')
                msg = email.message_from_string(part)  #收到的邮件包
                parseHeader(msg)
                parseBody(msg)
        pcount += 1
        if pcount > count:
            break

上面的msg包含了邮件本身的所有信息,我们感兴趣的有from, to, cc, subject, body等,分别代表了发件人,收件人,抄送列表,标题和邮件主体。python提供了email库帮助从message里提取。

  subject = message.get('Subject')
        # subject=str(message)
        # if subject is not None:
        h = email.header.Header(subject, charset='utf-8')
        dh = email.header.decode_header(h)
        subject = str(dh[0][0], encoding="utf-8")
        subject = encoded_words_to_text(subject)
        # .encode('utf-8')
        # print(h)
        # # 发件人
        from_sb = encoded_words_to_text(email.utils.parseaddr(message.get('from'))[0])
        if len(from_sb) == 0:
            from_sb = encoded_words_to_text(email.utils.parseaddr(message.get('from'))[1])
        # # 收件人
        to_sb = email.utils.parseaddr(message.get('to'))[1]
        # # 抄送人
        cc = email.utils.parseaddr(message.get_all('cc'))[1]
        # try:
        fmt = "ddd, D MMM YYYY HH:mm:ss Z"

        # date = arrow.get(message['Date'], fmt)
        date = arrow.get(message['Received'].split(';')[1], fmt)

        print(f"{from_sb:30} {subject:80} {date.humanize():20}")

arrow是python的一个第三方时间库,humanize可以生成one month ago这样容易懂的格式。

encoded_words_to_text方法是专门用来处理=?utf-8?q?打头的字符串的,因为电子邮件设计当初是只考虑ASCII码的,因为unicode还没诞生!为了支持unicode,又兼容以前的邮件,所以引入了这样的字符串格式。

def encoded_words_to_text(encoded_words):
    if not encoded_words.startswith("=?"):
        return encoded_words
    encoded_word_regex = r'=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}='
    charset, encoding, encoded_text = re.match(encoded_word_regex, encoded_words, flags=re.IGNORECASE).groups()
    if encoding.upper() == 'B':
        byte_string = base64.b64decode(encoded_text)
    elif encoding.upper() == 'Q':
        byte_string = quopri.decodestring(encoded_text)
    return byte_string.decode(charset)

###用smtplib发送邮件
发送相对于接收就很简单了,在用QQ授权码登录smtp.qq.com服务器后调用sendemail就可以了,唯一要注意的一点是sendmail的msg参数是指email的所有内容,并没有提供subject和body的专门参数。所以我们需要用换行符分开。

def send_mail(fromaddr, toaddrs, subject, body):
    # Add the From: and To: headers at the start!
    msg = ("From: %s\r\nTo: %s\r\nSubject: %s\n\n%s"
           % (fromaddr, ", ".join(toaddrs), subject, body))
    while True:  # 从命令行接收邮件内容,直到连按两下回车
        try:
            line = input()
        except EOFError:
            break
        if not line:
            break
        msg = msg + line
    print("Message length is", len(msg))
    server = SMTP_SSL('smtp.qq.com')
    server.set_debuglevel(1)  #打开调试
    server.login("111111@qq.com", "gzoyimtltnqsbdba")
    server.sendmail(fromaddr, toaddrs, msg)
    server.quit()

扫码关注公众号,获取最新文章
qrcode_for_gh_49497593f54f_258 (2).jpg

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!