c++ - 当文件通过 SMTP 发送时,它会丢失一些字节。C++
问题描述
我正在尝试通过 SMTP 发送电子邮件,我发送多部分邮件,包含文本部分和应用程序/八位字节流部分。当我尝试发送非 *.txt" 文件时,例如 .jpg 或 .docx,它已损坏并且丢失了一些字节。例如,当我尝试发送文件 123.docx 时,此文件的大小为 166 020 字节.我在我的电子邮件中收到文件,但它只有 166 006,我无法打开它。变量“total”显示发送的字节数正确。我的代码如下:
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
int fileSize(char fileName[])
{
std::streampos fsize = 0;
std::ifstream myfile (fileName, ios::in); // File is of type const char*
fsize = myfile.tellg(); // The file pointer is currently at the beginning
myfile.seekg(0, ios::end); // Place the file pointer at the end of file
fsize = myfile.tellg() - fsize;
myfile.close();
cout << "size is: " << fsize << " bytes.\n";
return fsize;
}
int main() {
char text[2048];
//connecting to smtp server
//sending DATA
strcpy(text,"DATA\n");
send(s,text,strlen(text),0);
recv(s,text,sizeof(text),0);
cout<<"recv - "<<text<<endl;
//FROM field
strcpy(text,"FROM: laboratory4_mm@rambler.ru\n");
send(s,text,strlen(text),0);
//TO field
strcpy(text,"TO: ");
strcat(text,reciever);
strcat(text,"\n");
send(s,text,strlen(text),0);
// SUBJECT field
char subject[2048];
cout<<"Enter the theme of the letter"<<endl;
cin.getline(subject,2048);
strcpy(text,"SUBJECT: ");
strcat(text,subject);
strcat(text,"\n");
send(s,text,strlen(text),0);
// delimeter of multipart message
strcpy(text,"Content-Type: multipart/mixed; boundary=\"---nsabnqeaSA43ds2\"\n");
send(s,text,strlen(text),0);
//Text part
strcpy(text,"-----nsabnqeaSA43ds2\nContent-Type: text/plain; charset=utf8\nContent-Transfer-Encoding: 8bit\n\n");
send(s,text,strlen(text),0);
cout<<"Enter the text:"<<endl;
cin.getline(text,2048);
send(s,text,strlen(text),0);
//File part
char fileName[256];
cout<<"Enter file name: ";
cin.getline(fileName,255);
int size = fileSize(fileName);
char fileLength[1024];
itoa(size,fileLength,10);
cout<<fileLength<<endl;
strcpy(text,"\n-----nsabnqeaSA43ds2 \nContent-Type: application/octet-stream\nContent-Length: ");
strcat(text,fileLength);
strcat(text,"\nContent-Transfer-Encoding: binary\nContent-Disposition: attachment;\n\n");
send(s,text,strlen(text),0);
ifstream fin;
fin.open(fileName,ios::binary);
char *buf = new char[1024];
int readBytes;
int total =0;
while((readBytes = fin.read(buf,1024).gcount())>0) {
int sent= send(s,buf,readBytes,0);
total+=sent;
delete buf;
buf = new char[1024];
}
fin.close();
delete buf;
cout<< total<<endl;
strcpy(text,"\n-----nsabnqeaSA43ds2--\n");
send(s,text,strlen(text),0);
// telling that DATA is over
strcpy(text,"\n.\n");
send(s,text,strlen(text),0);
fout<<text;
recv(s,text,sizeof(text),0);
cout<<"recv - "<<text<<endl;
//Disconnecting from server
return 0;
}
解决方案
MIME 编码中有几个基本错误,这里:
首先,空行应该将标题与内容分开。空行丢失:
strcpy(text,"Content-Type: multipart/mixed; boundary=\"---nsabnqeaSA43ds2\"\n");
此处生成一个换行符。
strcpy(text,"-----nsabnqeaSA43ds2\nContent-Type: text/plain; charset=utf8\nContent-Transfer-Encoding: 8bit\n\n");
邮件内容从这里开始,前面没有空行。
此外,边界分隔符之前的换行符是边界分隔符的逻辑部分,因此也缺少换行符。有关详细信息,请参阅 MIME 文档。
strcpy(text,"\n-----nsabnqeaSA43ds2 \nContent-Type: application/octet-stream\nContent-Length: ");
请注意,此处您在边界分隔符之前显式发送换行符,因此您必须了解此要求。
第二:
while((readBytes = fin.read(buf,1024).gcount())>0) {
int sent= send(s,buf,readBytes,0);
按原样发送二进制文件的内容?那不会飞的。尽管它可能是正确的 MIME 编码,也可能不是正确的 MIME 编码,但 SMTP 仍然是基于纯文本的传输协议。有一个用于传输二进制数据的扩展,但显示的代码没有使用它。
照原样,这是未定义行为的 SMTP 版本。没有保证的结果。如果您需要可靠地附加此文件,则必须对其进行 base64 编码。
推荐阅读
- python - Geopandas - 试图在 shapemap 上获取确切位置
- javascript - Google Maps API - 信息窗口中的图像幻灯片
- chef-infra - 如何从删除中恢复厨师节点对象?
- python - 根据存储在字符串、元组中的不同值创建字符串条件
- twilio - TaskRouter:离开队列
- python - Django 访问表单中的外键字段
- sharepoint - PowerApps 表单不会将外部数据保存到 SharePoint 列表
- python - 使用 OpenCV 和 Python 进行立体校正的问题
- sql - SQL 查询(加入?)
- android - AndroidManifest 上 ENOENT 的 Cordova 插件添加失败