关于SMTP那个程序的参考资料
来源:互联网 发布:js promise 阮一峰 编辑:程序博客网 时间:2024/05/17 00:53
♦第一个参考资料是某牛人写的C的SMTP协议:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
const char *MailData = "From: "leo"<xxxxx@gmail.com> "
"Subject: It's a test mail! . ";
int main(int argc, char *argv[])
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
struct hostent *pHostent = NULL;
SOCKET server = INVALID_SOCKET;
struct sockaddr_in service;
int retConnect = 0;
char Buffer[1024] = {0};
if(WSAStartup(wVersionRequested, &wsaData) != 0){
printf("Error at WSAStartup() ");
goto WSACleanup;
}
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create a Socket
if(server == INVALID_SOCKET){
printf("Error at socket(): %ld ", WSAGetLastError());
goto WSACleanup;
}
pHostent = gethostbyname("smtp.126.com"); //Get the Mail Server name
if(pHostent == NULL){
printf("The Host Name is Invalid... ");
goto WSACleanup;
}
service.sin_family = AF_INET;
memcpy(&service.sin_addr.s_addr, pHostent->h_addr_list[0],
pHostent->h_length);
service.sin_port = htons(25);
//Connect to the remote Mail Server
retConnect = connect(server, (struct sockaddr*)&service, sizeof(service));
if(retConnect == SOCKET_ERROR){
printf("Failed to connect. ");
goto WSACleanup;
}
printf("Connect to %s.... ", inet_ntoa(service.sin_addr));
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Failed to connect. ");
goto WSACleanup;
}else{
printf("%s ", Buffer);
}
//Send "HELO Server.... " to the Mail Server
retConnect = send(server, "HELO Server.... ", strlen("HELO
Server.... "), 0);
if(retConnect == SOCKET_ERROR){
printf("Send HELO to the Mail Failure. ");
goto WSACleanup;
}else{
printf("HELO Server.... ");
}
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Failed to connect. ");
goto WSACleanup;
}else{
printf("%s ", Buffer);
}
//Send "AUTH LOGIN " to the Mail Server
retConnect = send(server, "AUTH LOGIN ", strlen("AUTH LOGIN "), 0);
if(retConnect == SOCKET_ERROR){
printf("Send "AUTH LOGIN" to Mail Failure. ");
goto WSACleanup;
}else{
printf("AUTH LOGIN ");
}
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Receive Data From Mail Server Failure. ");
goto WSACleanup;
}else{
printf("%s ", Buffer);
}
//Send UserName to the Mail Server. The UserName is Encoded by Base64.
retConnect = send(server, "bGJleW9uZDRrb21h ",
strlen("bGJleW9uZDRrb21h "), 0);
if(retConnect == SOCKET_ERROR){
printf("Send UserName to the Mail Failure. ");
goto WSACleanup;
}else{
printf("UserName ");
}
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Receive Data From the Mail Server Failure. ");
goto WSACleanup;
}else{
printf("%s ", Buffer);
}
//Send Password to the Mail Server The Password is Encoded by Base64.
retConnect = send(server, "bGJleW9uZDRrb21h ",
strlen("bGJleW9uZDRrb21h "), 0);
if(retConnect == SOCKET_ERROR){
printf("Send Password to Mail Failure. ");
goto WSACleanup;
}else{
printf("Password ");
}
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Receive Data From the Mail Server Failure. ");
goto WSACleanup;
}else{
printf("%s ", Buffer);
}
//Send "Mail From: " File to the Mail Server, sender's Mail Address
retConnect = send(server, "MAIL FROM: <lbeyond4koma@126.com> ",
strlen("MAIL FROM: <lbeyond4koma@126.com> "), 0);
if(retConnect == SOCKET_ERROR){
printf("Send "Mail From: " to Mail Failure. ");
goto WSACleanup;
}else{
printf("MAIL FROM: <lbeyond4koma@126.com> ");
}
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Receive Data From Mail Server Failure. ");
goto WSACleanup;
}else{
Buffer[retConnect] = ' ';
printf("%s ", Buffer);
}
//Send "RCPT TO: " File to the Mail Server, receiver 's Mail Address
retConnect = send(server, "RCPT TO: <dl88250@gmail.com> ", strlen("RCPT
TO: <dl88250@gmail.com> "), 0);
if(retConnect == SOCKET_ERROR){
printf("Send "RCPT TO: " to Mail Failure. ");
goto WSACleanup;
}else{
printf("RCPT TO: <dl88250@gmail.com> ");
}
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Receive Data From the Mail Server Failure. ");
goto WSACleanup;
}else{
printf("%s ", Buffer);
}
//Send "Data" Fiele to the Mail Server, start to Send mail
retConnect = send(server, "Data ", strlen("Data "), 0);
if(retConnect == SOCKET_ERROR){
printf("Send "Data" Field to Mail Failure... ");
goto WSACleanup;
}else{
printf("Data ");
}
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Receive Data From Mail Server Failure... ");
goto WSACleanup;
}else{
printf("%s ", Buffer);
}
//Send Mail data to the the Mail Server
retConnect = send(server, MailData, strlen(MailData), 0);
if(retConnect == SOCKET_ERROR){
printf("Send Context Of Mail to Mail Failure... ");
goto WSACleanup;
}else{
printf("%s ", MailData);
}
//Receive Data From the Mail Server
ZeroMemory(Buffer, sizeof(Buffer));
retConnect = recv(server, Buffer, sizeof(Buffer), 0);
if(retConnect == SOCKET_ERROR){
printf("Receive Data From Mail Server Failure... ");
goto WSACleanup;
}else{
printf("%s ", Buffer);
}
//Send "QUIT" Context to the Mail Server
retConnect = send(server, "QUIT ", strlen("QUIT "), 0);
if(retConnect == SOCKET_ERROR){
printf("Send "Quit" to Mail Failure... ");
goto WSACleanup;
}else{
printf("Quit ");
}
printf("Send Mail Successful! ");
WSACleanup:{
if(server != INVALID_SOCKET){
closesocket(server);
}
WSACleanup();
}
system("pause");
return 0;
}
♦第二个是VC的
void CMailerDlg::OnOk()
{
UpdateData(TRUE);
CString Serv = "EHLO"+m_Server+"/r/n";
CString From = "MAIL FROM :<"+m_From+">/r/n";
CString To = "RCPT TO :<"+m_To+">/r/n";
CString Text = m_Message+"/r/n/r/n./r/n";
char *MailMessage[]=
{
Serv.GetBuffer(1),
From.GetBuffer(1),
To.GetBuffer(1),
"DATA/r/n",
Text.GetBuffer(1),
"QUIT/r/n",
NULL
};
WSADATA Wsa;
WSAStartup(0x0101,&Wsa);
SOCKET s = socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN sin;
sin.sin_addr.s_addr=inet_addr(m_Server);
sin.sin_family=AF_INET;
sin.sin_port=htons(25);
if(connect(s,(LPSOCKADDR)&sin,sizeof(sin))==SOCKET_ERROR)
MessageBox("Error:can't connect to server:(","Error",MB_OK|MB_ICONERROR);
int iLength=0;
int iEnd=0;
char sBuff[255]="";
int iMsg=0;
do{
iLength=recv(s,(LPSTR)sBuff+iEnd,sizeof(sBuff)-iEnd,0);
iEnd+=iLength;
sBuff[iEnd]='/0';
send(s,(LPSTR)MailMessage[iMsg],strlen(MailMessage[iMsg]),0);
iMsg++;
}while(MailMessage[iMsg]);
closesocket(s);
WSACleanup();
}
♦关于SMTP的理论部分文档
SMTP网络协议编程实现文档
SMTP协议简介
最常用的网络服务之一是电子邮件(E-mail)。 电子邮件用于把包含文本、视频或图片的单条报文发送给一个或者多个收件人。 简单邮件传输协议(Simple Mail Transfer Protocol,SMTP)是在因特网中用于电子邮件的标准机制。 SMTP通过使用发送方SMTP和接收方SMTP进程来发送和接收E-mail消息,这些进程执行E-mail的传送和接收服务。 SMTP服务器监听TCP 25号端口,并对客户端发送的合法命令做出响应。
邮件传输过程
从发件人到收件人之间的邮件传输过程由三个阶段构成:
·第一阶段:电子邮件从用户代理进入本地服务器。邮件并不是直接传送到远程服务器中的,因为远程服务器不能保证始终可用。 所以,邮件在发送前会一直保存在本地服务器中。用户代理使用SMTP客户端软件,而本地服务器使用SMTP服务器软件。
·第二阶段:电子邮件由本地服务器中继传递。 在这一阶段,远程服务器作为SMTP服务器,而本地服务器作为SMTP客户端。 电子邮件分发给远程服务器,而不是远程用户代理。 原因是SMTP报文必须由始终处于运行状态的服务器接收,服务器必须不间断运行的原因是由于邮件可能随时到达。 然而,人们经常在一天的工作结束时关闭计算机, 所以,通常情况下,组织机构会分派一台计算机作为邮件服务器,运行SMTP服务器程序。 电子邮件由这台邮件服务器接收,存储在用户的邮箱中,便于以后检索。
·第三阶段:远程用户代理使用邮件访问协议,如POP3或者IMAP,来访问邮箱并获取邮件。
SMTP标准及扩展命令
SMTP命令
作 用
HELO
用于开始会话,通常在HELO后跟客户机的主机名(hostname)
MAIL
用于指出发起会话的发件人,通常在MAIL后面跟From参数来指定发件人
RCPT
用于指定该消息的接收人,通常在RCPT后面跟To参数来指定收件人
DATA
表示客户端开始向服务器端发送消息(邮件) 正文
RSET
放弃当前的数据传输
VRFY
用以确定指定的收件人在服务器端是合法的(在发送邮件正文之前确定邮箱存在), 考虑到这个功能有一定的安全隐患,此命令在Exchange中不被支持,SMTP服务器总是返回“非法地址”
TURN
交换客户端和服务器角色,允许客户端触发服务器端的邮件传送(此命令也很少被使用)
EHLO(扩展)
作为标准HELO的替代者,客户端发送EHLO来跟服务器确定其对ESMTP的支持程度, 服务器会返回一个它所支持的ESMTP命令字列表给客户端。
ATRN(扩展)
TURN命令的增强,在启用TURN之前需要身份认证。
ETRN(扩展)
TURN命令的增强,功能上与TURN类似,但是通过创建另外一个独立的会话完成TURN报文传送。
Pipelining(扩展)
允许SMTP客户端在服务器响应之前以异步的方式连续发送若干的命令字。 例如,可以在获得服务器确认之前,连续发送多个RCPT命令字,这样可以实现在慢速网络上的高效通信。
BDAT(扩展)
此命令字替代DATA,允许客户端采用批量的方式传送消息报文,可以在一定程度上降低接收方的负载。
AUTH(扩展)
允许客户端使用基本验证、Windows集成验证(NTLM和Kerberos)与服务器进行身份认证, 进行身份认证也是避免SMTP服务器被relay的重要手段。
STARTTLS(扩展)
用来表示客户端希望能够与服务器建立一个基于TLS的加密会话。
XEXCH50(扩展)
用以传送Exchange服务器间专用的报头数据。
SMTP会话过程
SMTP在TCP协议25号端口监听连接请求,建立TCP连接后,客户端发送HELO命令以标识发件人自己的身份。 然后客户端发送MAIL命令服务器端正希望以OK作为响应,表明准备接收。 客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行,服务器端则表示是否愿意为收件人接受邮件。 协商结束,发送邮件,用命令DATA发送,以.表示结束输入内容一起发送出去。 结束此次发送,用QUIT命令退出。
♦其实这个才是最强的,他把附件啊,什么的都实现了的,但是他不是用SOCKET来做的,是调用本地邮件客户端来做的
/////////////////////////////////////////////////////////////////////////////
// CSendEMailDlg message handlers
BOOL CSendEMailDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//获取当前路径
CString szPath("");
GetModuleFileName(NULL,szPath.GetBuffer(MAX_PATH),MAX_PATH);
szPath.ReleaseBuffer();
szPath = szPath.Left(szPath.ReverseFind('//') + 1);
//从readme文件中读取邮件的正文内容
CString szFileName = szPath + "//Readme.txt";
CFileFind find;
bool bRet = find.FindFile(szFileName);
find.Close();
if(!bRet)
{
HRSRC hSrc = FindResource(NULL,MAKEINTRESOURCE(IDR_README),_T("OWNER_DATA"));
if(hSrc != NULL)
{
HGLOBAL hGlobal = LoadResource(NULL,hSrc);
if(hGlobal != NULL)
{
LPVOID lp = LockResource(hGlobal);
DWORD dwSize = SizeofResource(NULL,hSrc);
CFile file;
if(file.Open(szFileName,CFile::modeCreate|CFile::modeWrite))
{
file.Write(lp,dwSize);
file.Close();
}
FreeResource(hGlobal);
}
}
}
CFile file;
if(file.Open(szFileName,CFile::modeRead))
{
DWORD dwLen = file.GetLength();
m_szText.ReleaseBuffer();
file.Read(m_szText.GetBuffer(dwLen),dwLen);
file.Close();
m_szText.ReleaseBuffer();
UpdateData(false);
}
m_list.AddString(szFileName);
return TRUE; // return TRUE unless you set the focus to a control
}
void CSendEMailDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CSendEMailDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CSendEMailDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//DEL void CSendEMailDlg::OnShellExecute()
//DEL {
//DEL /* UpdateData(true);
//DEL
//DEL if(m_szEmail.IsEmpty()) m_szEmail = m_szDefaultEMail;
//DEL m_szEmail = "mailto:" + m_szEmail;
//DEL
//DEL ShellExecute(NULL,NULL,m_szEmail,NULL,NULL,SW_SHOW);*/
//DEL }
/*********************************************************************
* 函数名称:CSendEMailDlg::OnAddAttachment
* 说明: 添加附件到列表框中
*********************************************************************/
//DEL void CSendEMailDlg::OnAddAttachment()
//DEL {
//DEL CFileDialog dlg(true,NULL,NULL,OFN_ALLOWMULTISELECT);
//DEL
//DEL if(dlg.DoModal() == IDOK)
//DEL {
//DEL POSITION pos = dlg.GetStartPosition();
//DEL while(pos != NULL)
//DEL {
//DEL m_list.AddString(dlg.GetNextPathName(pos));
//DEL }
//DEL }
//DEL }
/*********************************************************************
* 函数名称:CSendEMailDlg::OnSendMapi
* 说明: 调用MAPI函数发送邮件。摘自 VC98/MFC/SRC/DOCMAPI.CPP
*********************************************************************/
void CSendEMailDlg::OnSendMapi()
{
UpdateData(true);
//加载MAPI32.DLL动态库
HMODULE hMod = LoadLibrary("MAPI32.DLL");
if (hMod == NULL) //加载动态库失败
{
AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD);
return;
}
//获取发送邮件的函数地址
ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG);
(FARPROC&)lpfnSendMail = GetProcAddress(hMod, "MAPISendMail");
if (lpfnSendMail == NULL)
{
AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL);
return;
}
int nFileCount = m_list.GetCount(); //有多少个附件需要发送
//分配内存保存附件信息 不能使用静态数组,因为不知道要发送附件的个数
MapiFileDesc* pFileDesc = (MapiFileDesc*)malloc(sizeof(MapiFileDesc) * nFileCount);
memset(pFileDesc,0,sizeof(MapiFileDesc) * nFileCount);
//分配内存保存附件文件路径
TCHAR* pTchPath = (TCHAR*)malloc(MAX_PATH * nFileCount);
CString szText;
for(int i = 0;i < nFileCount;i++)
{
TCHAR* p = pTchPath + MAX_PATH * i;
m_list.GetText(i,szText);
strcpy(p,szText);
(pFileDesc + i)->nPosition = (ULONG)-1;
(pFileDesc + i)->lpszPathName = p;
(pFileDesc + i)->lpszFileName = p;
}
//收件人结构信息
MapiRecipDesc recip;
memset(&recip,0,sizeof(MapiRecipDesc));
recip.lpszAddress = m_szEmailMAPI.GetBuffer(0);
recip.ulRecipClass = MAPI_TO;
//邮件结构信息
MapiMessage message;
memset(&message, 0, sizeof(message));
message.nFileCount = nFileCount; //文件个数
message.lpFiles = pFileDesc; //文件信息
message.nRecipCount = 1; //收件人个数
message.lpRecips = &recip; //收件人
message.lpszSubject = m_szSubject.GetBuffer(0); //主题
m_szText.ReleaseBuffer();
message.lpszNoteText= m_szText.GetBuffer(0); //正文内容
//保存本程序窗口指针,因为发完邮件后要返回本程序的窗口
CWnd* pParentWnd = CWnd::GetSafeOwner(NULL, NULL);
//发送邮件
int nError =
(0, 0,
&message, MAPI_LOGON_UI|MAPI_DIALOG, 0);
if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT
&& nError != MAPI_E_LOGIN_FAILURE)
{
AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND);
}
//返回程序
pParentWnd->SetActiveWindow();
//不要忘了释放分配的内存
free(pFileDesc);
free(pTchPath);
FreeLibrary(hMod);
}
void CSendEMailDlg::OnAbout()
{
CAboutDlg dlg;
dlg.DoModal();
}
void CSendEMailDlg::OnChangeEmail()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
void CSendEMailDlg::OnChangeEmail2()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
void CSendEMailDlg::OnOK()
{
// TODO: Add extra validation here
CDialog::OnOK();
}
void CSendEMailDlg::OnChangeText()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
- 关于SMTP那个程序的参考资料
- 关于Unicode的参考资料
- 关于电感储能的参考资料
- 关于YAFFS2文件系统移植的一些参考资料
- 关于suricate 的一些参考资料汇总
- 微信小程序参考资料
- PHP邮件发送的程序 SMTP验证
- 基于SMTP的JAVA邮件发送程序
- 基于SMTP的JAVA邮件发送程序!
- 关于TrackBack一些参考资料
- 关于SMTP协议发送邮件的总结
- SMTP-关于邮件编码的格式
- 关于smtp和pop3的端口
- 一个关于SMTP 的封装类
- 对那个IOCCC程序的进一步分析
- 那个找不到工作的iOS程序猿
- 那个找不到工作的iOS程序猿
- 关于那个OPC大会新闻的翻译
- SAP读书笔记
- comments on "the sun also rises"
- ::system has not been declared 的问题
- sina博客字体背景改变 friendzg2008
- 好好学习,天天向上
- 关于SMTP那个程序的参考资料
- 红警2韩国使用全面分析
- 第三次作业
- MS-SQL server 中Northwind和Pubs的中文E-R图
- Tkinter教程之Canvas篇(4)
- SAP 46C access key破解详细说明
- 在iframe的name不定时,根据被包含页面大小动态改变iframe的大小(by quqi99)
- 我的名言
- 关于windows减肥