ESP32中使用micropython模拟SMTP发送带MIME格式附件的邮件

本文描述了如何使用micropython发送一封带附件的邮件。主要使用socket链接,并使用smtp协议,构造一封带文件附件的邮件,并发送到指定邮箱。

附件是采用二进制方式读取,并一次性读入内存进行base64编码,由于我使用了esp32,内存有限,因此也不能发送太大的附件,不加spiram的情况下,几十k的附件勉强过得去。注意文件是放在esp32的根目录下的,如果不是,请自行修改路径代码。

本文的目的主要是了解如何用MIME格式去构造带附件的邮件。

作者水平有限,欢迎批评指正。

def sendMail(subjectStr,contentStr,attachFileName):
    #MIME邮件结构:
    #1.邮件头mailHead,详细内容见后。邮件头中会定义该邮件为multipart/mixed,并定义边界符boundary "---part1"
    #2.邮件头mailHead与邮件体mailBody的分隔符(一个空行\r\n)
    #3.邮件体mailBody。边界符的用法:
    #----part1(第一层级的边界符,level1.part1开始)
    #Content-Type: multipart/alternative;(定义第二个层级)
    #boundary="----Part2"(第二个层级的边界符)
    #----Part2(第二层级的边界符,level2.part1)
    #Content-Type: text/plain;(第二层级第1部分的定义)
    #charset="us-ascii"
    #Content-Transfer-Encoding: base64
    #BalaBala................内容
    #----Part2(第二层级的边界符,level2.part2)
    #Content-Type: text/html;(第二层级第2部分的定义)
    #charset="us-ascii"
    #Content-Transfer-Encoding: quoted-printable
    #BalaBala................内容
    #----Part2--(第二层级的结束边界符,最后多加两个--表示结束)
    
    #----part1(第一层级的边界符,level1.part2)
    #Content-Type: application/octet-stream;
    #  name="a.jpg"
    #Content-Transfer-Encoding: base64
    #Content-Disposition: attachment;
    #  filename="a.jpg"
    #BalaBala.....内容
    #----part1--(第一层结束)
    #4.邮件结束。"\r\n.\r\n"
    
    
    senderMailBoxAddr="fat0xff@aliyun.com"
    receiverMailBoxAddr="fat0xff@aliyun.com"
    mailServerAddr="smtp.aliyun.com"
    mailServerPort=25
    connectAddr=socket.getaddrinfo(mailServerAddr, mailServerPort)[0][-1]
    
    mailServerCmd_MAILFROM = "MAIL FROM:<"+senderMailBoxAddr+">\r\n"
    mailServerCmd_RCPTTO="RCPT TO:<"+receiverMailBoxAddr+">\r\n"
    mailServerCmd_DATA = "DATA\r\n"
    mailServerCmd_QUIT="QUIT\r\n"
    
    
    mailHead_From="From:<"+senderMailBoxAddr+">\r\n"
    mailHead_To="To:<"+receiverMailBoxAddr+">\r\n"
    mailHead_Subject="Subject:"+subjectStr+"\r\n"
    mailHead_XMailer="X-Mailer:shadowstar's mailer"+"\r\n"
    mailHead_MIMEVer="MIME-Version: 1.0"+"\r\n"
    mailHead_ContentType="Content-Type: multipart/mixed; \n"+"  boundary=\"=====001_NextPart167448323667_=====\"\r\n"
    #汇总mailHead
    mailHead=mailHead_From+mailHead_To+mailHead_Subject+mailHead_XMailer+mailHead_MIMEVer+mailHead_ContentType
    
    mailBody_Lv1Start="--=====001_NextPart167448323667_=====\r\n"#第一层段001开始的标识
    
    mailBody_Lv2Dim="Content-Type: multipart/alternative;\n"+"  boundary=\"=====002_NextPart167448323667_=====\"\r\n"#定义第二层段002,文本和超文本
    mailBody_Lv2Start="--=====002_NextPart167448323667_=====\r\n"#第二层段开始
    mailBody_Lv2Part1ContentType="Content-Type: text/plain; charset=\"UTF-8\"\r\n"
    mailBody_Lv2Part1ContentCode="Content-Transfer-Encoding: base64\r\n"
    mailBody_Lv2Part1Content=ubinascii.b2a_base64(contentStr.encode()).decode()+"\r\n"
    mailBody_Lv2End="--=====002_NextPart167448323667_=====--\r\n"#第二层段结束
    #汇总mailBodyLv2
    mailBody_Lv2=mailBody_Lv2Dim+mailBody_Lv2Start+mailBody_Lv2Part1ContentType+mailBody_Lv2Part1ContentCode\
                  +mailBody_Lv2Part1Content+mailBody_Lv2End

    mailBodyLv1_ContentCode="Content-Transfer-Encoding: base64\r\n"
    mailBodyLv1_ContentType="Content-Type:image/jpeg; name=\"a.jpg\"\r\n"
    mailBodyLv1_ContentDispo="Content-Disposition: attachment; filename=\"a.jpg\"\r\n\r\n"
    file=open(attachFileName,"rb")
    filebuf=file.read()
    time.sleep(3)    
    mailBodyLv1_Content=ubinascii.b2a_base64(filebuf).decode()+"\r\n"
    mailBodyLv1_End="\n--=====001_NextPart167448323667_=====--\r\n\r\n"
    #LV1过大,不再汇总
    
    mailBody=mailBody_Lv1Start+mailBody_Lv2+mailBody_Lv1Start+mailBodyLv1_ContentCode+mailBodyLv1_ContentType\
              +mailBodyLv1_ContentDispo+mailBodyLv1_Content+mailBodyLv1_End
    
    #邮件头与正文间用一个空行作为隔开标志。邮件必须以"\r\n.\r\n"结尾
    msg=mailHead+"\r\n"+mailBody+"\r\n.\r\n"

    

    print(len(msg))
    


    clientSocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    clientSocket.connect(connectAddr)
    recv=clientSocket.recv(1024)
    print(recv)

    heloCommand="HELO Alice\r\n"
    clientSocket.send(bytes(heloCommand.encode()))
    recv1=clientSocket.recv(1024)
    print(recv1.decode())

    loginini = b'AUTH LOGIN\r\n'
    userCommand=ubinascii.b2a_base64(b'fat0xff@aliyun.com').decode()+'\r\n'
    passwordCommand=ubinascii.b2a_base64(b'YourMailBoxPassword').decode()+'\r\n'
    clientSocket.send(loginini)
    recv2 = clientSocket.recv(1024).decode('utf-8')
    print('222+ ',recv2)

    clientSocket.send(userCommand.encode())
    recv3 = clientSocket.recv(1024).decode('utf-8')
    print('333+ ',recv3)

    clientSocket.send(passwordCommand.encode())
    recv4 = clientSocket.recv(1024).decode('utf-8')
    print('444+ ',recv4)
    print('-----------------------------------')

    clientSocket.send(bytes(mailServerCmd_MAILFROM.encode()))                             #send mail, had to convert to bytes
    check=clientSocket.recv(1024)
    print(check)

    #Send RCPT TO command and print server response.
    clientSocket.send(bytes(mailServerCmd_RCPTTO.encode()))                               #recieve, had to convert to bytes
    check1=clientSocket.recv(1024)
    print(check1)                                                           #print confirmation of working messages

    #Send DATA command and print server response.
    clientSocket.send(bytes(mailServerCmd_DATA.encode()))                                 #DATA, had to convert to bytes
    check2=clientSocket.recv(1024)
    print(check2)                                                           #print confirmation of working messages

    #Message ends with a single period.
    #clientSocket.send(bytes((mailHead_From+mailHead_To+mailHead_Subject+msg+endmsg).encode()))                #Concatinate bits for message
    clientSocket.send(bytes((msg).encode()))                #Concatinate bits for message
    check3=clientSocket.recv(1024)
    print(check3)                                                           #print confirmation of working messages

    #Send QUIT command and get server response.
    clientSocket.send(bytes(mailServerCmd_QUIT.encode()))                              #Quit the session
    check4=clientSocket.recv(1024)
    print(check4)  


wifi_connect("wifiname","wifipassword")
sendMail("This is tile!","This is mail content!","a.jpg")
print(micropython.mem_info())
gc.collect()#邮件发送附件占用内存太大,发送完了即刻清理内存!
print(micropython.mem_info())

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值