Python网络编程:E-mail服务(三)MIME解析

http://blog.csdn.net/jinguangliu/article/details/45201975

简介

邮件的格式对所有不同的E-mail协议来说都非常重要。可以用两种方式来看email信息,简单文本信息和多用途Internet邮件扩展形式MIME(Mutlipurpose InternetMail Extensions).本文主要是讲解MIME格式。

MIME作用

为了能通过电子邮件发送非ASCII数据,IETF定义了多用途Internet邮件扩充MIME(Multipurpose Internet MailExtension)。MIME没有改动SMTP或POP3,也没有替代它们,而是允许用ASCII码对任意数据进行编码,然后在标准电子邮件中传输。

为了适应任意数据类型和表示,每个MIME邮件包含告知接收方数据类型和所用编码的信息。MIME的信息位于邮件首部中,MIME首部各行指明了MIME的版本,发送数据的类型以及将数据转换为ASCII码所用的编码格式。

MIME实例

下面的例子显示了一个MIME邮件,其中包含用标准GIF(Graphics InterchangeFormat)表示的一幅图片。GIF图像使用base64编码格式转换为7位ASCII码表示。

  1. From: bill@example.com  
  2. To: john@example.com  
  3. MIME-Version: 1.0  
  4. Content-Type: image/gif  
  5. Content-Transfer-Encoding: base64  
  6. .....date for the image......  
From: bill@example.com
To: john@example.com
MIME-Version: 1.0
Content-Type: image/gif
Content-Transfer-Encoding: base64
.....date for the image......

首部的MIME-Version表明该邮件使用MIME协议版本1.0编写邮件,Content-Type行声明数据是GIF图像,而Content-Transfer-Encoding行声明使用base64编码格式将图像转换为ASCII码。为了查看图像,接收方的邮件系统首先将base64编码转换成二进制,然后运行一个应用程序在用户屏幕上显示GIF图像。

MIME标准规定Content-Type声明必须含两个标识符:一个是内容类型(content type),一个是子类型(subtype),中间用”/”分开。
我们接下来显示一个纯文本信息的MIME邮件,读者可以参考上面的例子来理解MIME的编码
  1. Content-Type: text/plain; charset="us-ascii"  
  2. MIME-Version: 1.0  
  3. Content-Transfer-Encoding: 7bit  
  4. To: jinguang.liu@qq.com  
  5. From: jliu@163.com  
  6. Subject: This is a test email  
  7. Date: Wed, 22 Apr 2015 22:26:32 +0800  
  8. Message-ID: <20150422142632.10808.43927@bob-PC>  
  9.   
  10. Hello,  
  11.    this is an autotest email.  
  12. ---jliu.  
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
To: jinguang.liu@qq.com
From: jliu@163.com
Subject: This is a test email
Date: Wed, 22 Apr 2015 22:26:32 +0800
Message-ID: <20150422142632.10808.43927@bob-PC>

Hello,
   this is an autotest email.
---jliu.

MIME的Content-Type类型

标准定义了7种基本类型以及每种类型的子类型和传输编码。如image类型的子类型必须为jpeg或gif,text不能使用这两种类型。

7种基本内容类型:text(文本,例如一个文档),image(图像),audio(音频),video(视频),application(应用程序,程序的原始数据),multipart(多邮件部分,每个有单独的内容类型和编码方式),message(邮件,一个完整的电子邮件或对邮件的外部应用,如一个FTP服务器和文件名)。

MIME的multipart类型详解

MIME的多部分(multipart)内容类型很有用,因为它增加了相当大的灵活性。标准为多部分邮件定义了4种可能的子类型,每种子类型都提供重要功能。

混合(mixed)子类型:允许单个邮件含有多个独立的子部分,每个子部分可有独立的类型和编码。使用混合类型的多部分邮件可在单个邮件中包含文本、图片和音频等

替代(alternative)子类型: 允许单个邮件含有统一数据的多种表示。当给多个使用不同硬件和软件系统的接收方发送邮件时,替代类型的多部分邮件的多种表示非常有用,例如:用户发送文档时,既包括普通ASCII文本,也包含格式化的文档,从而允许支持格式化文档查看的客户端程序给用户显示格式化的文档。

并行(parallel)子类型:允许单个邮件含有必须一同查看的各个子部分(如视频和音频部分必须一起播放)

文摘(digest)子类型:允许单个邮件含有一系列其它邮件(如关于一次讨论的一系列邮件)

总结

本文介绍的MIME知识是通过Python email模块编写邮件的基础,能够使我们更加深入的理解email提供MIME功能。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 C++ 程序示例,用于发送 E-Mail,利用 SMTP 协议、Base64 编码和 MIME 格式。 ```c++ #include <iostream> #include <string> #include <cstdlib> #include <cstring> #include <sstream> #include <fstream> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") using namespace std; // 定义 Base64 编码的转换表 const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // Base64 编码函数 string base64_encode(const unsigned char* input, int length) { string output; int i = 0, j = 0; unsigned char char_array_3[3], char_array_4[4]; while (length--) { char_array_3[i++] = *(input++); if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (i = 0; (i < 4); i++) output += base64_table[char_array_4[i]]; i = 0; } } if (i) { for (j = i; j < 3; j++) char_array_3[j] = '\0'; char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (j = 0; (j < i + 1); j++) output += base64_table[char_array_4[j]]; while ((i++ < 3)) output += '='; } return output; } // MIME 格式 string create_mime(string from, string to, string subject, string content) { string mime; mime += "From: " + from + "\r\n"; mime += "To: " + to + "\r\n"; mime += "Subject: " + subject + "\r\n"; mime += "MIME-Version: 1.0\r\n"; mime += "Content-Type: text/plain; charset=utf-8\r\n"; mime += "Content-Transfer-Encoding: base64\r\n"; mime += "\r\n"; mime += base64_encode((const unsigned char*)content.c_str(), content.length()); mime += "\r\n.\r\n"; return mime; } // 发送邮件 bool send_mail(string server, string username, string password, string from, string to, string subject, string content) { // 创建连接 SOCKET sock; struct sockaddr_in serv_addr; sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(25); serv_addr.sin_addr.s_addr = inet_addr(server.c_str()); if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) { cerr << "Connect error!" << endl; return false; } // 接收信息 char buffer[1024] = { 0 }; recv(sock, buffer, sizeof(buffer), 0); // 发送 HELO 命令 string helo = "HELO " + server + "\r\n"; send(sock, helo.c_str(), helo.length(), 0); recv(sock, buffer, sizeof(buffer), 0); // 发送 AUTH LOGIN 命令 string auth_login = "AUTH LOGIN\r\n"; send(sock, auth_login.c_str(), auth_login.length(), 0); recv(sock, buffer, sizeof(buffer), 0); // 发送用户名 string base64_username = base64_encode((const unsigned char*)username.c_str(), username.length()); send(sock, base64_username.c_str(), base64_username.length(), 0); send(sock, "\r\n", 2, 0); recv(sock, buffer, sizeof(buffer), 0); // 发送密码 string base64_password = base64_encode((const unsigned char*)password.c_str(), password.length()); send(sock, base64_password.c_str(), base64_password.length(), 0); send(sock, "\r\n", 2, 0); recv(sock, buffer, sizeof(buffer), 0); // 发送 MAIL FROM 命令 string mail_from = "MAIL FROM: <" + from + ">\r\n"; send(sock, mail_from.c_str(), mail_from.length(), 0); recv(sock, buffer, sizeof(buffer), 0); // 发送 RCPT TO 命令 string rcpt_to = "RCPT TO: <" + to + ">\r\n"; send(sock, rcpt_to.c_str(), rcpt_to.length(), 0); recv(sock, buffer, sizeof(buffer), 0); // 发送 DATA 命令 string data = "DATA\r\n"; send(sock, data.c_str(), data.length(), 0); recv(sock, buffer, sizeof(buffer), 0); // 发送邮件内容 string mime = create_mime(from, to, subject, content); send(sock, mime.c_str(), mime.length(), 0); recv(sock, buffer, sizeof(buffer), 0); // 发送 QUIT 命令 string quit = "QUIT\r\n"; send(sock, quit.c_str(), quit.length(), 0); recv(sock, buffer, sizeof(buffer), 0); // 关闭连接 closesocket(sock); return true; } int main() { // 设置发送邮件的参数 string server = "smtp.gmail.com"; string username = "your_username@gmail.com"; string password = "your_password"; string from = "your_username@gmail.com"; string to = "[email protected]"; string subject = "Test Mail"; string content = "Hello World!"; // 发送邮件 if (send_mail(server, username, password, from, to, subject, content)) { cout << "Mail sent successfully!" << endl; } else { cerr << "Failed to send mail!" << endl; } return 0; } ``` 请注意,在实际使用中,您需要根据您选择的邮件服务器和帐户来调整程序中的参数。此外,该程序仅适用于 Windows 平台。如果您需要在其他平台上运行,您需要对代码进行相应调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值