使用SMTP协议来发送邮件

SMTP还是比较简单的,首先使用tcp协议连接自己邮箱的smtp服务器的25号端口,接着就是一次send给服务器发送命令,一次recv读取服务器的返回状态。

大家可以使用windows自带的telnet工具来测试学习smtp协议。

下面是C++实现的代码,参考了不少资料,其中的check_server_response()函数没写完,未考虑命令执行失败的情况。代码中使用了上一篇文章中的Base64编码的类:

class MailSender
{
public:
MailSender(const char *strSmtpServer, const char *strHost, const char *strMailFrom, const char *strPasswd, const char *strSendTo, const char *strSubject, const char *strContent)
{
_strSmtpServer = strSmtpServer;
_strHost = strHost;
_strMailFrom = strMailFrom;
_strPasswd = strPasswd;
_strSendTo = strSendTo;
_strSubject = strSubject;
_strContent = strContent;
_socket = INVALID_SOCKET;
}

virtual ~MailSender()
{
if (_socket != INVALID_SOCKET)
{
closesocket(INVALID_SOCKET);
}
}

int send_mail()
{
int (MailSender::*routines[])() =
{
&MailSender::connect_server,
&MailSender::send_helo,
&MailSender::send_ehlo,
&MailSender::send_auth_login,
&MailSender::send_userid,
&MailSender::send_passwd,
&MailSender::send_mail_from,
&MailSender::send_rcpt_to,
&MailSender::send_data,
&MailSender::send_content,
&MailSender::send_quit,
};

for (int i = 0; i < sizeof(routines) / sizeof(routines[0]); ++i)
{
if ((this->*routines[i])())
{
return false;
}
}

return true;
}

private:

/**
* 连接服务器
*/
int connect_server()
{
addrinfo aiHints;
addrinfo *aiList = 0;

do
{
memset(&aiHints, 0, sizeof(aiHints));
aiHints.ai_family = AF_INET;
aiHints.ai_socktype = SOCK_STREAM;
aiHints.ai_protocol = IPPROTO_TCP;

if (getaddrinfo(_strSmtpServer, 0, &aiHints, &aiList))
{
break;
}

_socket = socket(AF_INET, SOCK_STREAM, 0);

sockaddr_in addr_server = *reinterpret_cast<sockaddr_in*>(aiList->ai_addr);
addr_server.sin_port = htons(25);

if (connect(_socket, (sockaddr*)&addr_server, sizeof addr_server))
{
break;
}

freeaddrinfo(aiList);

return check_server_response();

} while (false);

if (aiList)
{
freeaddrinfo(aiList);
}

if (INVALID_SOCKET != _socket)
{
closesocket(_socket);
_socket = INVALID_SOCKET;
}

return 1; // error
}

int send_helo()
{
char szCmdBuffer[256] = "HELO ";
strcat_s(szCmdBuffer, _strHost);
strcat_s(szCmdBuffer, " \r\n");
int send_bytes = strlen(szCmdBuffer);
if (send_bytes != send(_socket, szCmdBuffer, send_bytes, 0))
{
return 1; // error
}
return check_server_response();
}

int send_ehlo()
{
char szCmdBuffer[256] = "EHLO ";
strcat_s(szCmdBuffer, _strHost);
strcat_s(szCmdBuffer, " \r\n");
int send_bytes = strlen(szCmdBuffer);
if (send_bytes != send(_socket, szCmdBuffer, send_bytes, 0))
{
return 1; // error
}
return check_server_response();
}

int send_auth_login()
{
char szCmdBuffer[256] = "AUTH LOGIN\r\n";
int send_bytes = strlen(szCmdBuffer);
if (send_bytes != send(_socket, szCmdBuffer, send_bytes, 0))
{
return 1; // error
}
return check_server_response();
}

int send_userid()
{
Base64Encode encoder;

int buffer_length = encoder.get_need_length(strlen(_strMailFrom)) + 3;
char *base64_userid = new char[buffer_length];
memset(base64_userid, 0, buffer_length);
encoder.encode_data(_strMailFrom, strlen(_strMailFrom), base64_userid, &buffer_length);

#pragma warning(push)
#pragma warning(disable:4996)
strcat(base64_userid, "\r\n");
#pragma warning(push)

if (send(_socket, base64_userid, strlen(base64_userid), 0) != strlen(base64_userid))
{
return 1;
}

return check_server_response();
}

int send_passwd()
{
Base64Encode encoder;

int buffer_length = encoder.get_need_length(strlen(_strPasswd)) + 3;
char *base64_userid = new char[buffer_length];
memset(base64_userid, 0, buffer_length);
encoder.encode_data(_strPasswd, strlen(_strPasswd), base64_userid, &buffer_length);

#pragma warning(push)
#pragma warning(disable:4996)
strcat(base64_userid, "\r\n");
#pragma warning(push)

if (send(_socket, base64_userid, strlen(base64_userid), 0) != strlen(base64_userid))
{
return 1;
}

return check_server_response();
}

int send_mail_from()
{
char buffer[512] = { 0 };
sprintf_s(buffer, "MAIL FROM: <%s>\r\n", _strMailFrom);
if (send(_socket, buffer, strlen(buffer), 0) != strlen(buffer))
{
return 1;
}
return check_server_response();
}

int send_rcpt_to()
{
char buffer[512] = { 0 };
sprintf_s(buffer, "RCPT TO: <%s>\r\n", _strSendTo);
if (send(_socket, buffer, strlen(buffer), 0) != strlen(buffer))
{
return 1;
}
return check_server_response();
}

int send_data()
{
char szCmdBuffer[256] = "DATA\r\n";
int send_bytes = strlen(szCmdBuffer);
if (send_bytes != send(_socket, szCmdBuffer, send_bytes, 0))
{
return 1; // error
}
return check_server_response();
}

int send_content()
{
std::string strSendBuf;
strSendBuf.append("From: <");
strSendBuf.append(_strMailFrom);
strSendBuf.append(">\r\n");

strSendBuf.append("To: <");
strSendBuf.append(_strSendTo);
strSendBuf.append( ">\r\n" );

strSendBuf.append("Date: ");
strSendBuf.append("1989-04-29");
strSendBuf.append("\r\n");

strSendBuf.append("Subject: ");
strSendBuf.append(_strSubject);
strSendBuf.append("\r\n");

strSendBuf.append("X-Mailer: Gddsky mailer\r\nMIME-Version: 1.0\r\nContent-type: text/plain;charset=\"GB2312\"\r\n Content-Transfer-Encoding: base64\r\n\r\n");

strSendBuf.append(_strContent);
strSendBuf.append("\r\n.\r\n");
int send_bytres = send(_socket, strSendBuf.c_str(), (int)strSendBuf.size(), 0);
if (send_bytres != (int)strSendBuf.size())
{
return 1;
}
return check_server_response();

}

int send_quit()
{
char szCmdBuffer[256] = "QUIT\r\n";
int send_bytes = strlen(szCmdBuffer);
if (send_bytes != send(_socket, szCmdBuffer, send_bytes, 0))
{
return 1; // error
}
return check_server_response();
}

/**
* 返回0表示命令成功
*/
int check_server_response()
{
char recv_buffer[512] = { 0 };

do
{
int recv_bytes = recv(_socket, recv_buffer, sizeof recv_buffer, 0);
if (!recv_bytes)
{
break;
}

AtlTrace("%s", recv_buffer);

return 0;

} while (false);

return 1; // error
}

private:

WinSockApp _app;

SOCKET _socket;

/**
* SMTP服务器,E.G.: "smtp.126.com"
*/
const char *_strSmtpServer;

/**
* E.G.: "126.com"
*/
const char *_strHost;

const char *_strMailFrom;

const char *_strPasswd;

const char *_strSendTo;

const char *_strSubject;

const char *_strContent;
};

原文链接: https://www.cnblogs.com/avexer/archive/2012/11/25/3258314.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    使用SMTP协议来发送邮件

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/70556

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午2:24
下一篇 2023年2月9日 下午2:24

相关推荐