公司要做一个邮件发送程序,把程序中生成的报告发送到管理员的邮箱,由于考虑到不能使用邮件客户端,只好自己从smtp协议写起,这一路写来是相当郁闷。以新浪的smtp.sina.com为目标。
在这个网址上有个简单的邮件发送程序
http://www.codeproject.com/KB/IP/zsmtp.aspx#xx1394512xx
是在网上搜到的第一个最有用的程序,但他没有提供登录验证功能。经我该进登录验证,发送邮件代码如下:
说明:先用thundbird利用smtp.sina.com发了一封,用Ultra Network Sniffer截了smtp的包,用程序来发一样的命令序列到新浪服务器上,除最后的那个QUIT/r/n 命令服务器没有回复外,其余的命令都得到了和thundbird一样的回复,但是邮件没有发送成功,超级郁闷。如果谁在这方面有经验,请指教。或者有意研究的人,加我QQ:254909662我把工程文件传给你。工程文件是在VS2005下的。最后我只好用jmail邮件包来发送,程序是用c++写的,十分简单。我将贴在这个日志的最后。
这个是用thundbird发smtp.sina.com的命令序列:表示客户端发送
<----220 irxd5-202.sinamail.sina.com.cn ESMTP/r/n
--->EHLO [127.0.0.1]/r/n
<----250-irxd5-202.sinamail.sina.com.cn/r/n
<---250-8BITMIME/r/n250-SIZE 31457280/r/n250-AUTH PLAIN LOGIN/r/n250 AUTH=PLAIN LOGIN/r/n
--->AUTH PLAIN AGRp 注:此处省略了一些字母(密码)
<--- 235 #2.0.0 OK Authenticated/r/n
--->MAIL FROM: SIZE=315/r/n
ok/r/n
--->RCPT TO:/r/n
ok/r/n
--->DATA/r/n
<---354 Send from Rising mail proxy/r/n
---->Message-ID:
Date: Thu, 26 Feb 2009 13:01:31 +0800
From: digua
User-Agent: Thunderbird 2.0.0.19 (Windows/20081209)
MIME-Version: 1.0
To: digua254909662@163.com
Subject: bt
Content-Type: text/plain; charset=GB2312
Content-Transfer-Encoding: 7bit/r/n/r/ntest/r/n ./r/n
<---250
--->/r/nQUIT/r/n
<---221 irxd5-202.sinamail.sina.com.cn/r/n
下面是我的代码:
SOCKET CFastSmtp::_connectServerSocket(const char server[],
const unsigned short port)
{
int nConnect;
short nProtocolPort;
LPHOSTENT lpHostEnt;
LPSERVENT lpServEnt;
SOCKADDR_IN sockAddr;
SOCKET hServerSocket = INVALID_SOCKET;
lpHostEnt = gethostbyname(server);
if (lpHostEnt) {
hServerSocket = socket(PF_INET, SOCK_STREAM,DEFAULT_PROTOCOL);
if (hServerSocket != INVALID_SOCKET) {
if (port != NULL) {
nProtocolPort = port;
}else{
lpServEnt = getservbyname("mail", DEFAULT_PROTOCOL);
if (lpServEnt == NULL)
nProtocolPort = htons(IPPORT_SMTP);
else
nProtocolPort = lpServEnt->s_port;
}
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = nProtocolPort;
sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list);
nConnect = connect(hServerSocket, (PSOCKADDR)&sockAddr,
sizeof(sockAddr));
if(nConnect)
{
hServerSocket = INVALID_SOCKET;
std::cout <<"connect to server failed" < return hServerSocket;
}
char sReceiveBuffer[MAX_BUFFER_SIZE];
int recvLength;
if( (recvLength = recv(hServerSocket, (LPSTR)sReceiveBuffer, MAX_BUFFER_SIZE, NO_FLAGS) ) < 0)
{
return (hServerSocket = INVALID_SOCKET);
}
std::string response(sReceiveBuffer, recvLength);
std::cout <<"REC(" <<"220" <<")" < if( response.substr(0, 3) != "220")
{
return (hServerSocket = INVALID_SOCKET);
}
} else {
printf("Invalid socket/r/n");
throw;
}
}
return(hServerSocket);
}
bool CFastSmtp::ConnectServer(const char server[], const unsigned short port)
{
assert(server);
if (bCon)
Disconnect();
bCon=false;
hSocket = INVALID_SOCKET;
hSocket = _connectServerSocket(server, port);
if (hSocket != INVALID_SOCKET)
{
if( !simulateThundBird())
return false;
} else
{
printf("Invalid socket/r/n");
return (false);
}
bCon=true;
return (true);
}
bool CFastSmtp::simulateThundBird()
{
std::string msg;
msg = "EHLO [127.0.0.1]/r/n";
std::cout <<"Send:" <<"(" < if (send(hSocket, (LPSTR)msg.c_str(), msg.length(), NO_FLAGS) == SOCKET_ERROR)
{
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}
if( !rcvResponse("250"))
return false;
if( !rcvResponse("250"))
return false;
/*if( !rcvResponse("250"))
return false;
if( !rcvResponse("250"))
return false;
if( !rcvResponse("250"))
return false;*/
msg = "AUTH PLAIN AGRpMTQ1Njk1/r/n";这个是用thundbird发是截的数据,我删除了一些(涉及到邮箱密码)
std::cout <<"Send:" <<"(" < if (send(hSocket, (LPSTR)msg.c_str(), msg.length(), NO_FLAGS) == SOCKET_ERROR)
{
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}
if( !rcvResponse("235"))
return false;
return true;
}
bool CFastSmtp::Send()
{
// verify sender email
if (m_pcFromEmail == NULL) {
printf("Please specifiy a sender email address/r/n");
return (false);
}
BYTE sReceiveBuffer[4096];
int iLength = 0;
int iEnd = 0;
char buf[4096];
// get proper header
char* msgHeader = _formatHeader();
if (msgHeader == NULL) {
delete [] msgHeader;
printf("Failed to format message header/r/n");
return (false);
}
// start
strcpy(buf, "MAIL FROM: <");
strcat(buf, m_pcFromEmail);
strcat(buf, "> SIZE=316/r/n"); //这个316是我用thundbird发邮件截的,这个代码发和thundbird相同的邮件
std::cout <<"Send:" <<"(" < if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}
if( !rcvResponse("250"))
{
return false;
}
// create message receipts
char *token;
for(unsigned int i=0;i {
token = strtok(Recipients.at(i)->GetEmail(),"<");
token = strtok(NULL,"<");
if (token == NULL)
token = strtok(Recipients.at(i)->GetEmail(),"<");
strcpy(buf, "RCPT TO: <");
strcat(buf, token);
strcat(buf, "/r/n");
std::cout <<"Send:" <<"(" < if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}
if( !rcvResponse("250"))
{
return false;
}
}
for(unsigned int i=0;i token = strtok(CCRecipients.at(i)->GetEmail(),"<");
token = strtok(NULL,"<");
if (token == NULL)
token = strtok(Recipients.at(i)->GetEmail(),"<");
strcpy(buf, "RCPT TO: <");
strcat(buf, token);
strcat(buf, "/r/n");
std::cout <<"Send:" <<"(" < if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}
if( !rcvResponse("250"))
{
return false;
}
}
for(unsigned int i=0;i token = strtok(BCCRecipients.at(i)->GetEmail(),"<");
token = strtok(NULL,"<");
if (token == NULL)
token = strtok(Recipients.at(i)->GetEmail(),"<");
strcpy(buf, "RCPT TO: <");
strcat(buf, token);
strcat(buf, "/r/n");
std::cout <<"Send:" <<"(" < if (send(hSocket, (LPSTR)buf, strlen(buf), NO_FLAGS) == SOCKET_ERROR) {
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}
if( !rcvResponse("250"))
{
return false;
}
/*iLength = recv(hSocket, (LPSTR)sReceiveBuffer+iEnd,
sizeof(sReceiveBuffer)-iEnd,
NO_FLAGS);
iEnd += iLength;
sReceiveBuffer[iEnd] = '/0';*/
}
// init data
std::cout <<"Send:" <<"(" <<"DATA/r/n" <<")" < if (send(hSocket, (LPSTR)"DATA/r/n", strlen("DATA/r/n"), NO_FLAGS) == SOCKET_ERROR) {
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}
if( !rcvResponse("354"))
{
return false;
}
// send header
std::cout <<"Send:" <<"(" < if (send(hSocket,
(LPSTR)msgHeader, strlen(msgHeader), NO_FLAGS) == SOCKET_ERROR) {
printf("Socket send error: %d/r/n", WSAGetLastError());
delete [] msgHeader;
return (false);
}
// send body
// std::cout <<"Send:" <<"(" <// if (send(hSocket,
// (LPSTR)m_pcMsgBody, strlen(m_pcMsgBody), NO_FLAGS) == SOCKET_ERROR) {
// printf("Socket send error: %d/r/n", WSAGetLastError());
// return (false);
// }
signal end
//
// std::cout <<"Send:" <<"(" <<"/r/n./r/n" <<")" <// if (send(hSocket,
// (LPSTR)"/r/n./r/n", strlen("/r/n./r/n"), NO_FLAGS) == SOCKET_ERROR) {
// printf("Socket send error: %d/r/n", WSAGetLastError());
// return (false);
// }
if( !rcvResponse("250"))
{
return false;
}
/*std::cout <<"Send:" <<"(" <<"/r/n" <<")" < if (send(hSocket, (LPSTR)"/r/n", strlen("/r/n"), NO_FLAGS) == SOCKET_ERROR) {
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}*/
std::cout <<"Send:" <<"(" <<"QUIT/r/n" <<")" < if (send(hSocket, (LPSTR)"QUIT/r/n", strlen("QUIT/r/n"), NO_FLAGS) == SOCKET_ERROR) {
printf("Socket send error: %d/r/n", WSAGetLastError());
return (false);
}
if( !rcvResponse("221"))
{
return false;
}
delete [] msgHeader;
return (true);
}
用jmail从新浪smtp.sina.com发邮件到163的邮箱代码:
编译时把project->setting->c/c++ language下的把w_char当内置类型 改为否,要不会报不认识的符号:converttoBSTR错误。我用的是jmail4.5版本,http://www.vckbase.com/tools在这下的。安装目录里有教程。
#include
#import "../bin/jmail.dll" // 导入jmail.dll, 假如jmail.dll不在工程目录下,您需要写上完整路径
#pragma comment(lib, "comsupp.lib")
void main()
{
CoInitialize(NULL); // COM的初始化
{
// 创建SpeedMailer实例
jmail::IMessagePtr pMessage("JMail.Message");
// 发件人邮箱
pMessage->From = "username@sina.com";
// 发件人姓名
pMessage->FromName = "name";
// 添加收件人1, 无收件人姓名与PGP KEY
pMessage->AddRecipient("username@163.com","","");
// 优先级设置,1-5逐次降低, 3为中级
pMessage->Priority = 3;
// 编码方式设置, 默认是iso-8859-1
pMessage->Charset = "GB2312";
// 主题
pMessage->Subject = "bt";
// 正文
pMessage->Body = "test/r/n";
pMessage->MailServerPassWord = "password";
pMessage->MailServerUserName = "username";
pMessage->Send("smtp.sina.com.cn", VARIANT_FALSE);
}
CoUninitialize();
system("pause");
}
[转]smtp邮件发送程序
最新推荐文章于 2020-12-22 19:37:55 发布