⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smtp.cpp

📁 Visual C++网络通信编程实用案例精逊配套源码 光盘中存放的是书中涉及的所有实例的源代码和经过编译后的应用程序。所有程序均经过测试
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	{
	  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 + -