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

📄 smtp.cpp

📁 Visual C++网络通信编程实用案例精逊配套源码 光盘中存放的是书中涉及的所有实例的源代码和经过编译后的应用程序。所有程序均经过测试
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      CString sTemp(&buf[start]);

			// Now divide the substring into friendly names and e-mail addresses
      CSMTPAddress To;
			int nMark = sTemp.Find(_T('<'));
			if (nMark >= 0)
			{
				To.m_sFriendlyName = sTemp.Left(nMark);
				int nMark2 = sTemp.Find(_T('>'));
				if (nMark2 < nMark)
				{
          //An invalid string was sent in, fail the call
					delete [] buf;
          SetLastError(ERROR_INVALID_DATA);
          TRACE(_T("An error occurred while parsing the recipients string\n"));
          pRecipients->RemoveAll();
					return pRecipients;
				}
				// End of mark at closing bracket or end of string
				nMark2 > -1 ? nMark2 = nMark2 : nMark2 = sTemp.GetLength() - 1;
				To.m_sEmailAddress = sTemp.Mid(nMark + 1, nMark2 - (nMark + 1));
			}
			else
			{
				To.m_sEmailAddress = sTemp;
				To.m_sFriendlyName = _T("");
			}

      //Finally add the new recipient to the array of recipients
			To.m_sEmailAddress.TrimRight();
			To.m_sEmailAddress.TrimLeft();
			To.m_sFriendlyName.TrimRight();
			To.m_sFriendlyName.TrimLeft();
      if (To.m_sEmailAddress.GetLength())
        pRecipients->Add(To);

      //Move on to the next position
			start = pos + 1;
		}
	}
    
  //Tidy up the heap memory we have used
	delete [] buf;

	return pRecipients;
}

BOOL CSMTPMessage::AddMultipleRecipients(const CString& sRecipients, RECIPIENT_TYPE RecipientType)
{
  CSMTPAddressArray* pRecipients = ParseMultipleRecipients(sRecipients);

  //Add them to the correct array
  for (int i=0; i<pRecipients->GetSize(); i++)
  {
    CSMTPAddress& address = pRecipients->ElementAt(i);
    AddRecipient(address, RecipientType);
  }

  //Tidy up the heap memory
  delete pRecipients;

	return TRUE;
}

int CSMTPMessage::AddMultipleAttachments(const CString& sAttachments)
{
	BOOL nAttachments = 0;

	ASSERT(sAttachments.GetLength()); //允许空字符串
	
	//循环获得多个附件
	int length = sAttachments.GetLength();
	TCHAR* buf = new TCHAR[length + 1];	//申请空间
	_tcscpy(buf, sAttachments);
	for (int pos=0, start=0; pos<=length; pos++)
	{
		//每个附件之间通过","或者";"来分隔开的
		if ((buf[pos] == _T(',')) || (buf[pos] == _T(';')) || (buf[pos] == 0))
		{
			buf[pos] = 0;	
			CString sTemp(&buf[start]);

			//将附件增加到附件数组中
			CSMTPBodyPart attachment;
			sTemp.TrimRight();
			sTemp.TrimLeft();
			if (sTemp.GetLength())
			{
				BOOL bAdded = attachment.SetFilename(sTemp);
				if (bAdded)
				{
					++nAttachments;
					AddBodyPart(attachment);
				}
			}

			//移到下一个位置
			start = pos + 1;
		}
	}

	//清除临时缓冲区
	delete [] buf;

	return nAttachments;
}

CString CSMTPMessage::ConvertHTMLToPlainText(const CString& sHtml)
{
  //First pull out whats within the body tags
  CString sRet(sHtml);
  sRet.MakeUpper();
  int nStartCut = -1;
  int nStartBody = sRet.Find(_T("<BODY"));
  if (nStartBody != -1)
  {
    sRet = sHtml.Right(sHtml.GetLength() - nStartBody - 5);
    int nTemp = sRet.Find(_T('>'));
    nStartCut = nStartBody + nTemp + 6;
    sRet = sRet.Right(sRet.GetLength() - nTemp - 1);
  }
  sRet.MakeUpper();
  int nLength = sRet.Find(_T("</BODY"));

  //Finally do the actual cutting
  if (nLength != -1)
    sRet = sHtml.Mid(nStartCut, nLength);
  else
    sRet = sHtml;

  //Now strip all html tags
  int nStartTag = sRet.Find(_T('<'));
  int nEndTag = sRet.Find(_T('>'));
  while (nStartTag != -1 && nEndTag != -1)
  {
    sRet = sRet.Left(nStartTag) + sRet.Right(sRet.GetLength() - nEndTag - 1);
    nStartTag = sRet.Find(_T('<'));
    nEndTag = sRet.Find(_T('>'));
  }

  sRet.TrimLeft();
  sRet.TrimRight();
  return sRet;
}

void CSMTPMessage::AddTextBody(const CString& sBody)
{
  if (m_bMime)
  {
    CSMTPBodyPart* pTextBodyPart = m_RootPart.FindFirstBodyPart(_T("text/plain"));
    if (pTextBodyPart)
      pTextBodyPart->SetText(sBody);
    else
    {
      //Create a text body part
      CSMTPBodyPart oldRoot = m_RootPart;

      //Reset the root body part to be multipart/related
      m_RootPart.SetCharset(oldRoot.GetCharset());
      m_RootPart.SetText(_T("This is a multi-part message in MIME format"));
      m_RootPart.SetContentType(_T("multipart/mixed"));

      //Just add the text/plain body part (directly to the root)
      CSMTPBodyPart text;
      text.SetCharset(oldRoot.GetCharset());
      text.SetText(sBody);

      //Hook everything up to the root body part
      m_RootPart.AddChildBodyPart(text);
    }
  }
  else
  {
    //Let the body part class do all the work
    m_RootPart.SetText(sBody);
  }
}

void CSMTPMessage::AddHTMLBody(const CString& sBody, const CString& sContentBase)
{
  ASSERT(m_bMime); //You forgot to make this a MIME message using SetMime(TRUE)

  CSMTPBodyPart* pHtmlBodyPart = m_RootPart.FindFirstBodyPart(_T("text/html"));
  if (pHtmlBodyPart)
    pHtmlBodyPart->SetText(sBody);
  else
  {
    //Remember some of the old root settings before we write over it
    CSMTPBodyPart oldRoot = m_RootPart;

    //Reset the root body part to be multipart/related
    m_RootPart.SetCharset(oldRoot.GetCharset());
    m_RootPart.SetText(_T("This is a multi-part message in MIME format"));
    m_RootPart.SetContentType(_T("multipart/related"));

    //Just add the text/html body part (directly to the root)
    CSMTPBodyPart html;
    html.SetCharset(oldRoot.GetCharset());
    html.SetText(sBody);
    html.SetContentType(_T("text/html"));
    html.SetContentBase(sContentBase);

    //Hook everything up to the root body part
    m_RootPart.AddChildBodyPart(html);
  }
}

CString CSMTPMessage::GetHTMLBody()
{
  CString sRet;

  if (m_RootPart.GetNumberOfChildBodyParts())
  {
    CSMTPBodyPart* pHtml = m_RootPart.GetChildBodyPart(0);
    if (pHtml->GetContentType() == _T("text/html"))
      sRet = pHtml->GetText();
  }
  return sRet;
}

CString CSMTPMessage::GetTextBody()
{
  return m_RootPart.GetText();
}

void CSMTPMessage::SetMime(BOOL bMime)
{
  if (m_bMime != bMime)
  {
    m_bMime = bMime;

    //Reset the body body parts
    for (int i=0; i<m_RootPart.GetNumberOfChildBodyParts(); i++)
      m_RootPart.RemoveChildBodyPart(i);

    if (bMime)
    {
      CString sText = GetTextBody();

      //Remember some of the old root settings before we write over it
      CSMTPBodyPart oldRoot = m_RootPart;

      //Reset the root body part to be multipart/mixed
      m_RootPart.SetCharset(oldRoot.GetCharset());
      m_RootPart.SetText(_T("This is a multi-part message in MIME format"));
      m_RootPart.SetContentType(_T("multipart/mixed"));

      //Also readd the body if non - empty
      if (sText.GetLength())
        AddTextBody(sText);
    }
  }
}

BOOL CSMTPMessage::SaveToDisk(const CString& sFilename)
{
	//For correct operation of the T2A macro, see MFC Tech Note 59
	USES_CONVERSION;

  //Assume the worst
  BOOL bSuccess = FALSE;

  //Open the file for writing
  CFile outFile;
  if (outFile.Open(sFilename, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite))
  {
    try
    {
      //Write out the Message Header
      CString sHeader = GetHeader();
      char* pszHeader = T2A((LPTSTR) (LPCTSTR) sHeader);
      int nCmdLength = strlen(pszHeader);
      outFile.Write(pszHeader, nCmdLength);

	    //Write out the separator
      char* pszBodyHeader = "\r\n";
      nCmdLength = strlen(pszBodyHeader);
      outFile.Write(pszBodyHeader, nCmdLength);

      //Write out the rest of the message
      BOOL bHasChildParts = (m_RootPart.GetNumberOfChildBodyParts() != 0);
      if (bHasChildParts || m_bMime)
      {
        //Write the root body part (and all its children)
        WriteToDisk(outFile, &m_RootPart, TRUE);
      }
      else
      {
        //Send the body
        char* pszBody = T2A((LPTSTR) (LPCTSTR) m_RootPart.GetText());
        ASSERT(pszBody);
        nCmdLength = strlen(pszBody);

        //Send the body
        outFile.Write(pszBody, nCmdLength);
      }

      //Got to here, everything is ok
      bSuccess = TRUE;
    }
    catch(CFileException* pEx)
    {
      TRACE(_T("A file exception occured while trying to save the message to file %s\n"), sFilename);
      pEx->Delete();
    }
  }

  return bSuccess;
}

BOOL CSMTPMessage::WriteToDisk(CFile& file, CSMTPBodyPart* pBodyPart, BOOL bRoot)
{
  //Assume success
  BOOL bSuccess = TRUE;

  if (!bRoot)
  {
    //First send this body parts header
    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;
    }
		file.Write(pszHeader, nHeaderSize);

    //Free up the temp memory we have used
    pBodyPart->FreeHeader(pszHeader);
  }
  
  //Then the body parts body
  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;
  }
	file.Write(pszBody, nBodySize);

  //Free up the temp memory we have used
  pBodyPart->FreeBody(pszBody);

  //The recursively Send all the child body parts
  int nChildBodyParts = pBodyPart->GetNumberOfChildBodyParts();
  for (int i=0; i<nChildBodyParts && bSuccess; i++)
  {
    CSMTPBodyPart* pChildBodyPart = pBodyPart->GetChildBodyPart(i);
    bSuccess = WriteToDisk(file, pChildBodyPart, FALSE);
  }

  //Then the MIME footer if need be
  BOOL bSendFooter = (pBodyPart->GetNumberOfChildBodyParts() != 0);
  if (bSendFooter)
  {
    LPSTR pszFooter = NULL;
    int nFooterSize = 0;
    if (!pBodyPart->GetFooter(pszFooter, nFooterSize))
    {
		  TRACE(_T("Failed in call to send body parts footer, GetLastError returns: %d\n"), GetLastError());
		  return FALSE;
    }

	  file.Write(pszFooter, nFooterSize);

    //Free up the temp memory we have used
    pBodyPart->FreeFooter(pszFooter);
  }
  
  return bSuccess;
}




CSMTPConnection::CSMTPConnection()
{
  m_bConnected = FALSE;
#ifdef _DEBUG
  m_dwTimeout = 90000; //default timeout of 90 seconds when debugging
#else
  m_dwTimeout = 60000;  //default timeout of 60 seconds for normal release code
#endif
  m_nLastCommandResponseCode = 0;
  m_sHeloHostname = _T("auto");
}

CSMTPConnection::~CSMTPConnection()
{
  if (m_bConnected)
    Disconnect();
}

BOOL CSMTPConnection::Connect(LPCTSTR pszHostName, LoginMethod lm, LPCTSTR pszUsername, LPCTSTR pszPassword, int nPort, LPCTSTR pszLocalBoundAddress)
{
	USES_CONVERSION;

  //参数合法性检查
  ASSERT(pszHostName);

  //创建socket
  if (!m_SMTP.Create())
  {
    AfxMessageBox("不能创建socket");

	return FALSE;
  }

  //连接到服务器
  if (!m_SMTP.Connect(pszHostName, nPort, pszLocalBoundAddress))
  {
    if (pszLocalBoundAddress  && _tcslen(pszLocalBoundAddress))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -