python利用SMTP发送邮件

目录

发送文本邮件

发送混合格式邮件

主送、抄送、暗送


发送文本邮件

代码:

import smtplib
from email.mime.text import MIMEText

host = 'smtp.163.com'
user = 'csuzhucong@163.com' #发件人
password = '123456789'

def send_mail(to_list,subject,content):
    msg=MIMEText(content,'plain','utf-8')
    msg['from'] = user
    msg['to'] = ','.join(to_list) #注意,不是分号
    msg['subject'] = subject
    server = smtplib.SMTP()
    server.set_debuglevel(1)
    try:
        server.connect(host,25)
    except:
        print('connect fail')
        
    try:
        server.ehlo(user)
        server.login(user,password)
        print('login ok')
    except:
        print('login fail')

    try:
        server.sendmail(user, to_list, str(msg))
        server.close()
        return True
    except OSError:
        print('OSError')
        return False
    except:
        print('unexpect error')
        return False

def test():
    if(send_mail(['2802482801@qq.com'],'test','just test')):
        print('send ok')
    else:
        print('send fail')

if __name__ == '__main__':
    test()

解释:

1,smtplib是SMTP服务的模块,发送者邮箱要开启SMTP服务

2,host是发送者服务器地址,163邮箱的服务器地址是'smtp.163.com',其他邮箱的服务器地址可以在网上查,不过需要注意,QQ邮箱的服务器地址有2种,取决于发送者邮箱开启SMTP服务的时间

3,user是发送者的邮箱

4,password是user的授权码,不是邮箱密码,授权码是用来三方登录邮箱的(不要尝试以代码中的授权码登录我的邮箱。。。否则。。。你会发现授权码是错的,这里是这个代码唯一需要修改的地方,修改之后就能发邮件)

5,to_list是收件人列表,是列表类型,其中每个元素(至少1个元素)都是字符串,对应一个邮箱地址

6,subject是邮件标题,是字符串类型

7,content是邮件正文,是字符串类型

8, 'plain'是邮件类型,表示文本类型

9,','.join(to_list)是把列表转化成字符串,包含多个收件人,注意,连接符是逗号

10,server.set_debuglevel(1)是显示调试信息

11,SMTP的默认端口是25,某些邮箱(比如QQ邮箱)的端口不是25

12,ehlo和helo是SMTP的用户认证,ehlo的e是拓展的意思,就是对helo的拓展

发送混合格式邮件

前面详细讲解了如何发送文本文件,这里讲解如何发送html、附件和图片

html很简单,只要MIMEText中的参数改成html即可

附件也不难,难的是加图片

虽然图片可以当做附件发送,但是显然还需要一个加入正文的功能,方法是用html的img标签把图片加入。但是这样会有个问题,一般的邮箱都会将这种链接屏蔽掉。这个问题有2种解决方法,第一种是先把图片加入到附件,然后再把图片加入正文,第二种是利用MIMEMultipart的三层结构。第一种方法就不能把图片直接加入正文而不加入附件列表,所以我采用第二种。

代码:

#coding=utf-8
import smtplib
import json
from email.mime.text import MIMEText
from email.mime.image  import  MIMEImage
from email.mime.multipart import MIMEMultipart

host = ''
user = ''  #发件人
password = ''
sender = ''

def send_mail(to_list, subject, content,content_type='plain'):
    msg_alt = MIMEMultipart('alternative')
    msg_rel = MIMEMultipart('related')
    msg = MIMEMultipart('mixed')
    msg_rel.attach(msg_alt)
    msg.attach(msg_rel)
    msg['from'] = user
    msg['to'] = ','.join(to_list)   #注意,不是分号
    msg['subject'] = subject
    if(content_type == 'plain'):
        for type,item in content:
            if type == 'text':
                text = MIMEText(item,'plain','utf-8')
                msg_alt.attach(text)
            elif type == 'attach_path':
                attachment = get_attach(item)
                if(attachment):
                    msg.attach(attachment)
            else:
                #print('type error')
                pass
    elif content_type == 'html':
        mailBody = ''
        for type,item in content:
            if type == 'html':
                mailBody += item
            elif type == 'image_path':
                image = get_image(item)
                if(image):
                    con = '<p><img src=cid:'+ item +'></p>'
                    mailBody = mailBody + con
                    msg_rel.attach(image)
            elif type == 'attach_path':
                attachment = get_attach(item)
                if(attachment):
                    msg.attach(attachment)
            else:
                #print('type error')
                pass
        html = MIMEText(mailBody,'html','utf-8')
        msg_alt.attach(html)
    else:
        return False

    server = smtplib.SMTP()
    #server.set_debuglevel(1)
    try:
        server.connect(host,25)
    except:
        print('connect fail')

    try:
        server.ehlo(user)
        server.login(user,password)
        print('login ok')
    except:
        print('login fail')

    try:
        server.sendmail(sender, to_list, str(msg))
        server.close()
        return True
    except OSError:
        print('OSError')
        return False
    except:
        print('unexpect error')
        return False

#添加图片内容到正文
def get_image(image_path):
    try:
        fp = open(image_path,'rb')
    except:
        return None
    image = MIMEImage(fp.read())
    fp.close()
    image.add_header( 'Content-ID' ,  '<'+image_path+'>' )
    return image

#添加附件
def get_attach(attach_path):
    try:
        f = open(attach_path,'rb')
        att = MIMEText(f.read(),'base64', 'utf-8')
        f.close()
    except FileNotFoundError:
        print('FileNotFound')
        return None
    except:
        print('unexpect error')
        return None
    att['Content-Type'] = 'application/octet-stream'
    att['Content-Disposition'] = 'attachment; filename='+attach_path
    return att

def analysis(json_arg):
    arg = json.loads(json_arg)
    to_list = arg['to_list']
    subject = arg['subject']
    content = arg['content']
    content_type = 'plain'
    try:
        content_type = arg['content_type']
    except:
        pass
    return 

def test1():
    recv = ['']
    content = (('text','这不是垃圾邮件啊啊啊啊啊'),('attach_path','1.txt'))
    arg1 = {'to_list':recv, 'subject':'test', 'content':content}
    json_arg = json.dumps(arg1)
    if(analysis(json_arg)):
        print('send ok')
    else:
        print('send fail')

def test2():
    recv = ['']
    html = '<a href="http://www.baidu.com">百度链接</a>'
    content = (('html' ,'看图'),('attach_path','1.txt'),('image_path','1.jpg'),('image_path','2.png'),('html',html))  #html的值不一定非要html代码,普通字符串也行
    arg2 = {'to_list':recv, 'subject':'test', 'content':content,'content_type':'html'}
    json_arg = json.dumps(arg2)
    if(analysis(json_arg)):
        print('send ok')
    else:
        print('send fail')


if __name__ == '__main__':
    test1()
    test2()

'''
send_mail.py接口说明:
函数analysis(json_arg)只有1个参数,json_arg是json类型,元素有3-4个
4个元素的键依次是to_list,subject,content,content_type
(1)to_list是收件人列表,是列表类型,其中每个元素(至少1个元素)都是字符串,对应一个邮箱地址
(2)subject是邮件标题,是字符串类型
(3)content是元祖类型,每个元素(type,item)是邮件正文中的1个内容,
type是'text'或'html'或'attach_path'或'image_path',对应的item(都是字符串)分别代表文本、html代码、附件名、图片名(如果需要的话前面带上路径名)
(4)content_type是'plain'或'html',如果是'plain'(可以缺省)那么content是'text'或'attach_path',如果是'html'那么content是'html'或'attach_path'或'image_path'
'''

主送、抄送、暗送

前面我解释了如何发送各种内容的邮件,但是收件人都是主送,没有抄送和暗送。

相关代码如下:

msg['from'] = user
msg['to'] = ','.join(to_list)   #注意,不是分号
msg['subject'] = subject
server.sendmail(sender, to_list, str(msg))

要想实现抄送和暗送,只需要自定义收件人列表即可:

msg['from'] = user
msg['to'] = ','.join(to_list)   #注意,不是分号
msg['cc'] = ','.join(ccto_list)
receive = to_list
receive.extend(ccto_list)
receive.extend(bccto_list)
msg['subject'] = subject
server.sendmail(sender,receive, str(msg))

这样,邮件发送给receive,即所有人,但是邮件中只显示主送和抄送,不显示暗送。

那么所有人都知道主送人是哪些,抄送人是哪些,但是主送人和抄送人不知道暗送人是哪些(不知道有没有暗送人),而暗送人只知道自己是被暗送的,不知道有没有其他暗送人。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值