📄 smtp.cpp
字号:
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 + -