📄 smtp.cpp
字号:
{
AfxMessageBox("不能连接服务器");
}
else
{
AfxMessageBox("不能连接服务器");
}
return FALSE;
}
else
{
//连接成功
m_bConnected = TRUE;
//获得相应
if (!ReadCommandResponse(220))
{
TRACE(_T("An unexpected SMTP login response was received\n"));
Disconnect();
return FALSE;
}
//获得本地机器名
if (m_sHeloHostname == _T("auto"))
{
//获得主机名
char sHostName[100];
gethostname(sHostName, sizeof(sHostName));
TCHAR* pszHostName = A2T(sHostName);
m_sHeloHostname = pszHostName;
}
// 进行下一步连接,即进行SMTP会话
BOOL bConnectOk = FALSE;
if (lm != NoLoginMethod)
bConnectOk = ConnectESMTP(m_sHeloHostname, pszUsername, pszPassword, lm);
else
bConnectOk = ConnectSMTP(m_sHeloHostname);
// 如果失败,则断开连接
if (!bConnectOk)
{
Disconnect();
return FALSE;
}
return TRUE;
}
}
// 该函数是通过扩展SMTP会话方式连接服务器的
BOOL CSMTPConnection::ConnectESMTP(LPCTSTR pszLocalName, LPCTSTR pszUsername, LPCTSTR pszPassword, LoginMethod lm)
{
//验证参数
ASSERT(pszUsername);
ASSERT(pszPassword);
ASSERT(lm != NoLoginMethod);
USES_CONVERSION;
//发送EHLO命令
CString sBuf;
sBuf.Format(_T("EHLO %s\r\n"), pszLocalName);
LPCSTR pszData = T2A((LPTSTR) (LPCTSTR) sBuf);
int nCmdLength = strlen(pszData);
if (!m_SMTP.Send(pszData, nCmdLength))
{
return FALSE;
}
//检查Hello命令的响应
if (!ReadCommandResponse(250))
{
return FALSE;
}
BOOL bLoginOk = FALSE;
switch (lm)
{
#ifndef CSMTP_NORSA
case CramMD5Method:
{
bLoginOk = CramLogin(pszUsername, pszPassword); // CRAM-MD5 authentication
break;
}
#endif
case AuthLoginMethod:
{
bLoginOk = AuthLogin(pszUsername, pszPassword); // LOGIN authentication
break;
}
case LoginPlainMethod:
{
bLoginOk = AuthLoginPlain(pszUsername, pszPassword); // PLAIN authentication
break;
}
default:
{
ASSERT(FALSE);
break;
}
}
return bLoginOk;
}
// This function connects using standard SMTP connection i.e. HELO
BOOL CSMTPConnection::ConnectSMTP(LPCTSTR pszLocalName)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//Send the HELO command
CString sBuf;
sBuf.Format(_T("HELO %s\r\n"), pszLocalName);
LPCSTR pszData = T2A((LPTSTR) (LPCTSTR) sBuf);
int nCmdLength = strlen(pszData);
if (!m_SMTP.Send(pszData, nCmdLength))
{
TRACE(_T("An unexpected error occurred while sending the HELO command\n"));
return FALSE;
}
//check the response to the HELO command
return ReadCommandResponse(250);
}
BOOL CSMTPConnection::Disconnect()
{
BOOL bSuccess = FALSE;
//disconnect from the SMTP server if connected
if (m_bConnected)
{
char sBuf[10];
strcpy(sBuf, "QUIT\r\n");
int nCmdLength = strlen(sBuf);
if (!m_SMTP.Send(sBuf, nCmdLength))
TRACE(_T("Failed in call to send QUIT command, GetLastError returns: %d\n"), GetLastError());
//Check the reponse
bSuccess = ReadCommandResponse(221);
if (!bSuccess)
{
SetLastError(ERROR_BAD_COMMAND);
TRACE(_T("An unexpected QUIT response was received\n"));
}
//Reset all the state variables
m_bConnected = FALSE;
}
else
TRACE(_T("Already disconnected from SMTP server, doing nothing\n"));
//free up our socket
m_SMTP.Close();
return bSuccess;
}
BOOL CSMTPConnection::SendBodyPart(CSMTPBodyPart* pBodyPart, BOOL bRoot)
{
//Assume success
BOOL bSuccess = TRUE;
if (!bRoot)
{
//发送信件头
LPSTR pszHeader = NULL;
int nHeaderSize = 0;
if (!pBodyPart->GetHeader(pszHeader, nHeaderSize))
{
TRACE(_T("Failed in call to send body parts header, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
if (!m_SMTP.Send(pszHeader, nHeaderSize))
{
bSuccess = FALSE;
}
//释放空间
pBodyPart->FreeHeader(pszHeader);
}
//根信体内容
LPSTR pszBody = NULL;
int nBodySize = 0;
if (!pBodyPart->GetBody(pszBody, nBodySize))
{
TRACE(_T("Failed in call to send body parts body, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
if (!m_SMTP.Send(pszBody, nBodySize))
{
TRACE(_T("Failed in call to send body parts body, GetLastError returns: %d\n"), GetLastError());
bSuccess = FALSE;
}
//释放内存空间
pBodyPart->FreeBody(pszBody);
//发送附件
int nChildBodyParts = pBodyPart->GetNumberOfChildBodyParts();
for (int i=0; i<nChildBodyParts && bSuccess; i++)
{
CSMTPBodyPart* pChildBodyPart = pBodyPart->GetChildBodyPart(i);
bSuccess = SendBodyPart(pChildBodyPart, FALSE);
}
//发送发送MINE结束部分
BOOL bSendFooter = (pBodyPart->GetNumberOfChildBodyParts() != 0);
if (bSendFooter)
{
LPSTR pszFooter = NULL;
int nFooterSize = 0;
if (!pBodyPart->GetFooter(pszFooter, nFooterSize))
{
return FALSE;
}
if (!m_SMTP.Send(pszFooter, nFooterSize))
{
bSuccess = FALSE;
}
//释放内存
pBodyPart->FreeFooter(pszFooter);
}
return bSuccess;
}
BOOL CSMTPConnection::SendMessage(CSMTPMessage& Message)
{
USES_CONVERSION;
ASSERT(m_bConnected);
//发送Email命令
ASSERT(Message.m_From.m_sEmailAddress.GetLength());
CString sBuf;
sBuf.Format(_T("MAIL FROM:<%s>\r\n"), Message.m_From.m_sEmailAddress);
LPCSTR pszMailFrom = T2A((LPTSTR) (LPCTSTR) sBuf);
int nCmdLength = strlen(pszMailFrom);
if (!m_SMTP.Send(pszMailFrom, nCmdLength))
{
TRACE(_T("Failed in call to send MAIL command, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
//检查服务器响应
if (!ReadCommandResponse(250))
{
SetLastError(ERROR_BAD_COMMAND);
TRACE(_T("An unexpected MAIL response was received\n"));
return FALSE;
}
//发送RCPT命令,每一个接受者都需要发送一次
//必须有收信人
ASSERT(Message.GetNumberOfRecipients(CSMTPMessage::TO) +
Message.GetNumberOfRecipients(CSMTPMessage::CC) +
Message.GetNumberOfRecipients(CSMTPMessage::BCC));
//首先"TO"发送接收者
for (int i=0; i<Message.GetNumberOfRecipients(CSMTPMessage::TO); i++)
{
CSMTPAddress* pRecipient = Message.GetRecipient(i, CSMTPMessage::TO);
ASSERT(pRecipient);
if (!SendRCPTForRecipient(*pRecipient))
return FALSE;
}
//然后是 "CC" 接收者
for (i=0; i<Message.GetNumberOfRecipients(CSMTPMessage::CC); i++)
{
CSMTPAddress* pRecipient = Message.GetRecipient(i, CSMTPMessage::CC);
ASSERT(pRecipient);
if (!SendRCPTForRecipient(*pRecipient))
return FALSE;
}
//然后是"BCC" 接收者
for (i=0; i<Message.GetNumberOfRecipients(CSMTPMessage::BCC); i++)
{
CSMTPAddress* pRecipient = Message.GetRecipient(i, CSMTPMessage::BCC);
ASSERT(pRecipient);
if (!SendRCPTForRecipient(*pRecipient))
return FALSE;
}
//发送DATA命令
char* pszDataCommand = "DATA\r\n";
nCmdLength = strlen(pszDataCommand);
if (!m_SMTP.Send(pszDataCommand, nCmdLength))
{
TRACE(_T("Failed in call to send MAIL command, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
//检查DATA命令的响应
if (!ReadCommandResponse(354))
{
SetLastError(ERROR_BAD_COMMAND);
TRACE(_T("An unexpected DATA response was received\n"));
return FALSE;
}
//发送信息头
CString sHeader = Message.GetHeader();
char* pszHeader = T2A((LPTSTR) (LPCTSTR) sHeader);
nCmdLength = strlen(pszHeader);
if (!m_SMTP.Send(pszHeader, nCmdLength))
{
TRACE(_T("Failed in call to send the header, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
BOOL bHasChildParts = (Message.m_RootPart.GetNumberOfChildBodyParts() != 0);
if (bHasChildParts || Message.m_bMime)
{
//发送信件内容
if(!SendBodyPart(&Message.m_RootPart, TRUE))
return FALSE;
}
else
{
//Send the Header for the body (Note in the case of non mime emails, it is just a simple line separaror
char* pszBodyHeader = "\r\n";
nCmdLength = strlen(pszBodyHeader);
if (!m_SMTP.Send(pszBodyHeader, nCmdLength))
{
TRACE(_T("Failed in call to send the body header, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
char* pszBody = T2A((LPTSTR) (LPCTSTR) Message.m_RootPart.GetText());
ASSERT(pszBody);
nCmdLength = strlen(pszBody);
//发送信体
if (!m_SMTP.Send(pszBody, nCmdLength))
{
TRACE(_T("Failed in call to send the header, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
}
//发送邮件结束指示符
char* pszEOM = "\r\n.\r\n";
nCmdLength = strlen(pszEOM);
if (!m_SMTP.Send(pszEOM, nCmdLength))
{
TRACE(_T("Failed in call to send end of message indicator, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
//检查结束符响应
if (!ReadCommandResponse(250))
{
SetLastError(ERROR_BAD_COMMAND);
TRACE(_T("An unexpected end of message response was received\n"));
return FALSE;
}
return TRUE;
}
BOOL CSMTPConnection::OnSendProgress(DWORD /*dwCurrentBytes*/, DWORD /*dwTotalBytes*/)
{
//By default just return TRUE to allow the mail to continue to be sent
return TRUE;
}
BOOL CSMTPConnection::SendMessage(BYTE* pMessage, DWORD dwTotalBytes, CSMTPAddressArray& Recipients, const CSMTPAddress& From, DWORD dwSendBufferSize)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//paramater validity checking
ASSERT(m_bConnected); //Must be connected to send a message
//Send the MAIL command
ASSERT(From.m_sEmailAddress.GetLength());
CString sBuf;
sBuf.Format(_T("MAIL FROM:<%s>\r\n"), From.m_sEmailAddress);
LPCSTR pszMailFrom = T2A((LPTSTR) (LPCTSTR) sBuf);
int nCmdLength = strlen(pszMailFrom);
if (!m_SMTP.Send(pszMailFrom, nCmdLength))
{
TRACE(_T("Failed in call to send MAIL command, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
//check the response to the MAIL command
if (!ReadCommandResponse(250))
{
SetLastError(ERROR_BAD_COMMAND);
TRACE(_T("An unexpected MAIL response was received\n"));
return FALSE;
}
//Must be sending to someone
int nRecipients = Recipients.GetSize();
ASSERT(nRecipients);
//Send the RCPT command, one for each recipient
for (int i=0; i<nRecipients; i++)
{
CSMTPAddress& recipient = Recipients.ElementAt(i);
if (!SendRCPTForRecipient(recipient))
return FALSE;
}
//Send the DATA command
char* pszDataCommand = "DATA\r\n";
nCmdLength
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -