发信人: wenbobo(灌了拂衣去)
整理人: wenbobo(2002-06-06 11:12:21), 站内信件
|
【 在 headspring 的大作中提到:】
:像outlook和foxmail等等,都带有身份验证支持,我想实现它,请问它遵循什么标准呢?
:......
除了RFC,就是STD,平时多看看。这个是同事的日常练习程序,也不知道对不对,参考一下吧
// atmosmail.cpp : Defines the entry point for the console application.
//
#pragma comment (lib,"wsock32.lib")
#ifndef CMD_RESPONSE_SIZE
#define CMD_RESPONSE_SIZE 1024
#endif
#ifndef CMD_BLOCK_SIZE
#define CMD_BLOCK_SIZE 1024
#endif
#ifndef m_dwCmdTimeout
#define m_dwCmdTimeout 60
#endif
#ifndef MAXPATH
#define MAXPATH 100
#endif
#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <TCHAR.h>
#include <String>
SOCKET m_hSocket;
LPTSTR m_strResult;
bool m_bExtensions=true; // 默认情况下使用ESMTP协议
unsigned int m_LineWidth = 76;
//Base64解码表
const char BASE64_ENCODE_TABLE[64] = {
65, 66, 67, 68, 69, 70, 71, 72, // 00 - 07
73, 74, 75, 76, 77, 78, 79, 80, // 08 - 15
81, 82, 83, 84, 85, 86, 87, 88, // 16 - 23
89, 90, 97, 98, 99, 100, 101, 102, // 24 - 31
103, 104, 105, 106, 107, 108, 109, 110, // 32 - 39
111, 112, 113, 114, 115, 116, 117, 118, // 40 - 47
119, 120, 121, 122, 48, 49, 50, 51, // 48 - 55
52, 53, 54, 55, 56, 57, 43, 47 };// 56 - 63
///////////////////////base64
//获取Base64编码长度
int Base64EncodeSize(int iSize)
{
int nSize, nCR;
nSize = (iSize + 2) / 3 * 4 ;
nCR = nSize / m_LineWidth; //计算回车数量
nSize+= nCR * 2;
return nSize;
}
//////////////////////////////////////////////////////////
int base64_encode(char *pSrc, unsigned int nSize, char *pDest)
{
/*
* 对一段Buffer进行Base64编码
*
* pSrc 输入Buffer
* nSize Buffer长度
* pDest 输出缓冲
*
* 注: 输出Buffer的长度可以使用 Base64EncodeSize(int) 方法取得
*
* return: base64编码后的字符串的长度
*/
if ((pSrc == NULL) || (nSize <= 0)) return 0;
unsigned int iB, iInMax3, Len;
char *pInPtr, *pInLimitPtr;
char *OutPtr ;
pInPtr = pSrc;
iInMax3 = (nSize / 3) * 3;
OutPtr = pDest;
pInLimitPtr = pInPtr + iInMax3;
while (pInPtr != pInLimitPtr)
{
Len = 0;
while ((Len < m_LineWidth) && (pInPtr != pInLimitPtr))
{
iB = (unsigned char) *pInPtr++;
iB = iB << 8;
iB = iB | (unsigned char) *pInPtr++;
iB = iB << 8;
iB = iB | (unsigned char) *pInPtr++;
//以4 byte倒序写入输出缓冲
OutPtr[3] = BASE64_ENCODE_TABLE[iB & 0x3F];
iB = iB >> 6;
OutPtr[2] = BASE64_ENCODE_TABLE[iB & 0x3F];
iB = iB >> 6;
OutPtr[1] = BASE64_ENCODE_TABLE[iB & 0x3F];
iB = iB >> 6;
OutPtr[0] = BASE64_ENCODE_TABLE[iB];
OutPtr+=4;
Len+=4;
}
if (Len >= m_LineWidth)
{
*OutPtr++ = '\r'; //加上回车换行符
*OutPtr++ = '\n';
}
}
//设置尾部
switch (nSize - iInMax3)
{
case 1:
iB = (unsigned char) *pInPtr;
iB = iB << 4;
OutPtr[1] = BASE64_ENCODE_TABLE[iB & 0x3F];
iB = iB >> 6;
OutPtr[0] = BASE64_ENCODE_TABLE[iB];
OutPtr[2] = '='; //用'='也就是64码填充剩余部分
OutPtr[3] = '=';
OutPtr+=4;
break;
case 2:
iB = (unsigned char) *pInPtr++;
iB = iB << 8;
iB = iB | (unsigned char) *pInPtr;
iB = iB << 2;
OutPtr[2] = BASE64_ENCODE_TABLE[iB & 0x3F];
iB = iB >> 6;
OutPtr[1] = BASE64_ENCODE_TABLE[iB & 0x3F];
iB = iB >> 6;
OutPtr[0] = BASE64_ENCODE_TABLE[iB];
OutPtr[3] = '='; // Fill remaining byte.
OutPtr+=4;
break;
}
return (unsigned int) (OutPtr - pDest);
}
/////////////////////////////////////////////////////////////
// Send a command to the SMTP server and wait for a response
//if success return the integer message of the smtp server
//or failed return -1
int SendCmd(LPTSTR pszCmd)
{
FD_SET set;
TIMEVAL tv;
int nRet = 0;
DWORD dwTick;
CHAR szResult[CMD_RESPONSE_SIZE];
LPSTR pszPos;
LPSTR pszTok;
DWORD dwPosition;
DWORD dwLen;
DWORD dwMax;
BOOL bReportProgress = FALSE;
LPSTR pszBuff;
ZeroMemory(szResult,CMD_RESPONSE_SIZE);
FD_ZERO(&set);
// If we have a command to send, then send it.
if (pszCmd)
{
pszBuff = (LPSTR) malloc(lstrlen(pszCmd)+1);
lstrcpyA(pszBuff,pszCmd);
// Make sure the input buffer is clear before sending
nRet = 1;
while (nRet > 0)
{
FD_SET(m_hSocket,&set);
tv.tv_sec = 0;
tv.tv_usec = 0;
nRet = select(1,&set,NULL,NULL,&tv);
if (nRet == 1) nRet = recv(m_hSocket,szResult,CMD_RESPONSE_SIZE,0);
}
dwPosition = 0;
dwLen = lstrlen(pszCmd);
if (dwLen > CMD_BLOCK_SIZE) bReportProgress = TRUE;
while (dwLen != dwPosition)
{
dwMax = min(CMD_BLOCK_SIZE,dwLen - dwPosition);
printf("send char is %s\n",&pszBuff[dwPosition]);
nRet = send(m_hSocket,&pszBuff[dwPosition],dwMax,0);
if (nRet == SOCKET_ERROR)
{
free(pszBuff);
return nRet;
}
dwPosition += dwMax;
if (bReportProgress)
{
//
}
}
// Wait for the CMD to finish being sent
FD_ZERO(&set);
FD_SET(m_hSocket,&set);
nRet = select(1,NULL,&set,NULL,NULL);
free(pszBuff);
}
// Prepare to receive a response
ZeroMemory(szResult,CMD_RESPONSE_SIZE);
pszPos = szResult;
nRet=1;
// Wait for the specified timeout for a full response string
dwTick = GetTickCount();
while ((GetTickCount() - dwTick) < (m_dwCmdTimeout * 1000))
{
FD_SET(m_hSocket,&set);
tv.tv_sec = m_dwCmdTimeout - ((GetTickCount() - dwTick) / 1000);
tv.tv_usec = 0;
// Check the socket for readability
nRet = select(1,&set,NULL,NULL,&tv);
if (nRet == SOCKET_ERROR)
{
printf("error:read message from smtp server\n");
break;
}
// If the socket has data, read it.
if (nRet == 1)
{
nRet = recv(m_hSocket,pszPos,CMD_RESPONSE_SIZE - (pszPos - szResult),0);
printf("Message from smtp server:%s\n",pszPos);
// Treats a graceful shutdown as an error
if (nRet == 0) nRet = SOCKET_ERROR;
if (nRet == SOCKET_ERROR)
{
printf("error:read Null message from smtp server\n");
break;
}
// Add the data to the total response string & check for a LF
pszPos += nRet;
pszTok = strrchr(szResult,'\n');
if (pszTok)
{
// Truncate CRLF combination and exit our wait loop
pszTok --;
pszTok[0] = 0;
break;
}
}
}
// Assign the response string
m_strResult = szResult;
// Evaluate the numeric response code
if (nRet && (nRet != SOCKET_ERROR))
{
szResult[3] = 0;
nRet = atoi(szResult);
}
else nRet = -1;
return nRet;
}
int SendAuthentication(LPSTR Auth,LPSTR PassWord)
{
int length;
int nRet;
LPSTR pszBuff;
TCHAR szName[128];
TCHAR szPassWord[128];
nRet=SendCmd("Auth Login\r\n");
if (nRet != 334)
{
printf("Auth Login failed\r\n");
return nRet;
}
length=lstrlen(Auth);
pszBuff = (LPSTR) malloc(Base64EncodeSize(length)+1);
pszBuff[Base64EncodeSize(length)]=0;
base64_encode(Auth, length, pszBuff);
printf("Auth=%s\r\n",Auth);
printf("Auth=%s\r\n",pszBuff);
wsprintf(szName,(_T("%s\r\n")),pszBuff);
printf("%s\n",szName);
nRet=SendCmd(szName);
//if (nRet != 235)
length=lstrlen(PassWord);
pszBuff = (LPSTR) malloc(Base64EncodeSize(length));
pszBuff[Base64EncodeSize(length)]=0;
base64_encode(PassWord, length, pszBuff);
printf("PassWrod=%s\r\n",PassWord);
printf("PassWrod=%s\r\n",pszBuff);
wsprintf(szPassWord,(_T("%s\r\n")),pszBuff);
printf("%s\n",szPassWord);
nRet=SendCmd(szPassWord);
return 1;
}
// Initiate a conversation with the SMTP server
// Returns 0 if successful, or a positive
// error values if the SMTP server gave an error or failure response.
int SendHelo()
{
int nRet = 0;
TCHAR szName[32];
TCHAR szMsg[39];
DWORD dwSize = 32;
GetComputerName(szName,&dwSize);
printf("%s\n",szName);
wsprintf(szMsg,(_T("EHLO %s\r\n")),szName);
printf("%s\n",szMsg);
if (m_bExtensions)
nRet = SendCmd(szMsg);
if (nRet != 250)
{
szMsg[0] = 'H';
szMsg[1] = 'E';
nRet = SendCmd(szMsg);
}
if (nRet != 250)
return nRet;
return 0;
}
// Send a MAIL FROM command to the server
// Returns 0 if successful, or a positive
// error value if the SMTP server gave an error or failure response.
int SendFrom(LPTSTR pszFrom)
{
int nRet = 0;
TCHAR szMsg[MAX_PATH];
wsprintf(szMsg,_T("MAIL FROM:%s\r\n"),pszFrom);
while (1)
{
nRet = SendCmd(szMsg);
// Send authentication if required, and retry the command
if (nRet == 530) nRet = SendAuthentication("xxxx\r\n","*******\r\n");
else break;
}
// Raise an error if we failed
if (nRet != 250) return nRet;
return (nRet == 250) ? 0:nRet;
}
// Send a RCPT TO command to the server
// Returns 0 if successful, or a positive
// error value if the SMTP server gave an error or failure response.
int SendTo(LPTSTR pszTo)
{
int nRet;
TCHAR szMsg[MAX_PATH];
wsprintf(szMsg,_T("RCPT TO:%s\r\n"),pszTo);
nRet = SendCmd(szMsg);
if (nRet != 250 && nRet != 251) return (nRet);
return (nRet == 250 || nRet == 251) ? 0:nRet;
}
// Send the body of an e-mail message to the server
// Returns 0 if successful, or a positive
// error value if the SMTP server gave an error or failure response.
int SendData(LPSTR Message)
{
int nRet;
// Send the DATA command. We need a 354 to proceed
nRet = SendCmd(_T("DATA\r\n"));
if (nRet != 354)
{
return nRet;
}
// Parse the body of the email message
// Send the body and expect a 250 OK reply.
nRet = SendCmd(Message);
if (nRet != 250) return(nRet);
return (nRet == 250) ? 0:nRet;
}
// Tell the SMTP server we're quitting
// Returns 0 if successful, or a positive
// error value if the SMTP server gave an error or failure response.
int SendQuitCmd()
{
int nRet;
// if (!m_bConnected) return 0;
nRet = SendCmd(_T("QUIT\r\n"));
if (nRet != 221) return (nRet);
return (nRet == 221) ? 0:nRet;
}
////////////////////////////////////////////////////////////////////////////
///////////////////////////////MAIN( )//////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void main(int argc,char *argv[])
{
struct sockaddr_in server_addr;
struct hostent *hp;
int nRet;
WORD wVersionRequested;
WSADATA wsaData;
int err;
if (argc < 2)
{
printf("Usage is error!\n");
printf("Right usage:\n");
printf("Exmaple: client 10.38.0.119 25\n");
printf("OR: client smtp-ent.21cn.com 25\n");
return;
}
wVersionRequested=MAKEWORD(1,1);
err=WSAStartup(wVersionRequested, &wsaData);
if (err!=0)
{
perror("there is no DLL to use");
return;
}
if ( (LOBYTE(wsaData.wVersion)!=1) || (HIBYTE(wsaData.wVersion)!=1) )
{
perror("there is not right DLL");
WSACleanup();
return;
}
m_hSocket=socket(AF_INET,SOCK_STREAM,0);
if (m_hSocket<0)
{
perror("there is error in opening stream socket!");
return;
}
server_addr.sin_family=AF_INET;
hp=gethostbyname(argv[1]);
if(hp==0)
{
perror("cannot find hostname\n");
return;
}
memcpy((char *)&server_addr.sin_addr,(char *)hp->h_addr,hp->h_length);
server_addr.sin_port=htons((unsigned short)atoi(argv[2]));
//Before send data,listenning
//进行连接
if(connect(m_hSocket,(struct sockaddr*)&server_addr,sizeof(server_addr))<0)
{
perror("there is error in connecting stream socket");
return;
}
nRet = SendCmd(NULL);
if (nRet != 220)
{
//关闭socket
closesocket(m_hSocket);
WSACleanup();
return;
}
printf("220\n");
if (SendHelo())
{
//关闭socket
closesocket(m_hSocket);
WSACleanup();
return;
}
getchar();
SendAuthentication("[email protected]","*****");
getchar();
if (SendFrom("[email protected]"))
{
//关闭socket
closesocket(m_hSocket);
WSACleanup();
return;
}
getchar();
if (SendTo("[email protected]"))
{
//关闭socket
closesocket(m_hSocket);
WSACleanup();
return;
}
getchar();
if (SendData("Subject: test \r\n\r\nthis is a test\r\nhyx\r\n.\r\n"))
{
//关闭socket
closesocket(m_hSocket);
WSACleanup();
return;
}
getchar();
if (SendQuitCmd())
{
//关闭socket
closesocket(m_hSocket);
WSACleanup();
return;
}
printf("send is ok\n");
//关闭socket
closesocket(m_hSocket);
WSACleanup();
return;
}
---- ◢█◣◢█◣
◤◥◢█◤◥
◣◢█◤◣◢
◥█◤◥█◤ |
|