📄 smtp.cpp
字号:
bSuccess = TRUE;
pszBody = NULL;
nBodySize = 0;
}
}
else
TRACE(_T("No bodypart body text or filename specified!\n"));
}
else
{
//如果是文本内容
if (m_bQuotedPrintable)
{
//形成发送体
CString sBody = QuotedPrintableEncode(m_sText);
nBodySize = _tcslen(sBody);
pszBody = new char[nBodySize+1];
strcpy(pszBody, T2A((LPTSTR) (LPCTSTR) sBody));
}
else
{
nBodySize = _tcslen(m_sText);
pszBody = new char[nBodySize+1];
strcpy(pszBody, T2A((LPTSTR) (LPCTSTR) m_sText));
}
bSuccess = TRUE;
}
return bSuccess;
}
BOOL CSMTPBodyPart::GetFooter(LPSTR& pszFooter, int& nFooterSize)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//Form the MIME footer
CString sFooter;
sFooter.Format(_T("\r\n--%s--"), m_sBoundary);
nFooterSize = _tcslen(sFooter);
pszFooter = new char[nFooterSize+1];
strcpy(pszFooter, T2A((LPTSTR) (LPCTSTR) sFooter));
return TRUE;
}
int CSMTPBodyPart::GetNumberOfChildBodyParts() const
{
return m_ChildBodyParts.GetSize();
}
int CSMTPBodyPart::AddChildBodyPart(CSMTPBodyPart& bodyPart)
{
CSMTPBodyPart* pNewBodyPart = new CSMTPBodyPart(bodyPart);
pNewBodyPart->m_pParentBodyPart = this;
ASSERT(m_sContentType.GetLength());
return m_ChildBodyParts.Add(pNewBodyPart);
}
void CSMTPBodyPart::RemoveChildBodyPart(int nIndex)
{
CSMTPBodyPart* pBodyPart = m_ChildBodyParts.GetAt(nIndex);
delete pBodyPart;
m_ChildBodyParts.RemoveAt(nIndex);
}
CSMTPBodyPart* CSMTPBodyPart::GetChildBodyPart(int nIndex)
{
return m_ChildBodyParts.GetAt(nIndex);
}
CSMTPBodyPart* CSMTPBodyPart::GetParentBodyPart()
{
return m_pParentBodyPart;
}
void CSMTPBodyPart::FixSingleDot(CString& sBody)
{
int nFind = sBody.Find(_T("\n."));
if (nFind != -1)
{
CString sLeft(sBody.Left(nFind+1));
CString sRight(sBody.Right(sBody.GetLength()-(nFind+1)));
FixSingleDot(sRight);
sBody = sLeft + _T(".") + sRight;
}
}
CSMTPBodyPart* CSMTPBodyPart::FindFirstBodyPart(const CString sContentType)
{
for (int i=0; i<m_ChildBodyParts.GetSize(); i++)
{
CSMTPBodyPart* pBodyPart = m_ChildBodyParts.GetAt(i);
if (pBodyPart->m_sContentType == sContentType)
return pBodyPart;
}
return NULL;
}
CSMTPMessage::CSMTPMessage() : m_sXMailer(_T("CSMTPConnection v2.17")), m_bMime(FALSE)
{
}
CSMTPMessage::~CSMTPMessage()
{
//Free up the array memory
for (int i=0; i<m_ToRecipients.GetSize(); i++)
delete m_ToRecipients.GetAt(i);
m_ToRecipients.RemoveAll();
for (i=0; i<m_CCRecipients.GetSize(); i++)
delete m_CCRecipients.GetAt(i);
m_CCRecipients.RemoveAll();
for (i=0; i<m_BCCRecipients.GetSize(); i++)
delete m_BCCRecipients.GetAt(i);
m_BCCRecipients.RemoveAll();
}
void CSMTPMessage::SetCharset(const CString& sCharset)
{
m_RootPart.SetCharset(sCharset);
}
CString CSMTPMessage::GetCharset() const
{
return m_RootPart.GetCharset();
}
int CSMTPMessage::GetNumberOfRecipients(RECIPIENT_TYPE RecipientType) const
{
int nSize = 0;
switch (RecipientType)
{
case TO: nSize = m_ToRecipients.GetSize(); break;
case CC: nSize = m_CCRecipients.GetSize(); break;
case BCC: nSize = m_BCCRecipients.GetSize(); break;
default: ASSERT(FALSE); break;
}
return nSize;
}
int CSMTPMessage::AddRecipient(CSMTPAddress& recipient, RECIPIENT_TYPE RecipientType)
{
int nIndex = -1;
CSMTPAddress* pNewRecipient = new CSMTPAddress(recipient);
switch (RecipientType)
{
case TO: nIndex = m_ToRecipients.Add(pNewRecipient); break;
case CC: nIndex = m_CCRecipients.Add(pNewRecipient); break;
case BCC: nIndex = m_BCCRecipients.Add(pNewRecipient); break;
default: ASSERT(FALSE); break;
}
return nIndex;
}
void CSMTPMessage::RemoveRecipient(int nIndex, RECIPIENT_TYPE RecipientType)
{
switch (RecipientType)
{
case TO:
{
delete m_ToRecipients.GetAt(nIndex);
m_ToRecipients.RemoveAt(nIndex);
break;
}
case CC:
{
delete m_CCRecipients.GetAt(nIndex);
m_CCRecipients.RemoveAt(nIndex);
break;
}
case BCC:
{
delete m_BCCRecipients.GetAt(nIndex);
m_BCCRecipients.RemoveAt(nIndex);
break;
}
default:
{
ASSERT(FALSE);
break;
}
}
}
CSMTPAddress* CSMTPMessage::GetRecipient(int nIndex, RECIPIENT_TYPE RecipientType)
{
switch (RecipientType)
{
case TO: return m_ToRecipients.GetAt(nIndex); break;
case CC: return m_CCRecipients.GetAt(nIndex); break;
case BCC: return m_BCCRecipients.GetAt(nIndex); break;
default: ASSERT(FALSE); return (CSMTPAddress*) NULL; break;
}
}
int CSMTPMessage::AddBodyPart(CSMTPBodyPart& Attachment)
{
SetMime(TRUE); //Body parts implies Mime
return m_RootPart.AddChildBodyPart(Attachment);
}
void CSMTPMessage::RemoveBodyPart(int nIndex)
{
m_RootPart.RemoveChildBodyPart(nIndex);
}
CSMTPBodyPart* CSMTPMessage::GetBodyPart(int nIndex)
{
return m_RootPart.GetChildBodyPart(nIndex);
}
int CSMTPMessage::GetNumberOfBodyParts() const
{
return m_RootPart.GetNumberOfChildBodyParts();
}
void CSMTPMessage::AddCustomHeader(const CString& sHeader)
{
m_CustomHeaders.Add(sHeader);
}
CString CSMTPMessage::GetCustomHeader(int nIndex)
{
return m_CustomHeaders.GetAt(nIndex);
}
int CSMTPMessage::GetNumberOfCustomHeaders() const
{
return m_CustomHeaders.GetSize();
}
void CSMTPMessage::RemoveCustomHeader(int nIndex)
{
m_CustomHeaders.RemoveAt(nIndex);
}
CString CSMTPMessage::GetHeader()
{
//Hive away the locale so that we can restore it later. We
//require the English locale to ensure the date header is
//formed correctly
CString sOldLocale = _tsetlocale(LC_TIME, NULL);
_tsetlocale(LC_TIME, _T("english"));
//Form the Timezone info which will form part of the Date header
TIME_ZONE_INFORMATION tzi;
int nTZBias;
if (GetTimeZoneInformation(&tzi) == TIME_ZONE_ID_DAYLIGHT)
nTZBias = tzi.Bias + tzi.DaylightBias;
else
nTZBias = tzi.Bias;
CString sTZBias;
sTZBias.Format(_T("%+.2d%.2d"), -nTZBias/60, nTZBias%60);
//Create the "Date:" part of the header
CTime now(CTime::GetCurrentTime());
CString sDate(now.Format(_T("%a, %d %b %Y %H:%M:%S ")));
sDate += sTZBias;
//Create the "To:" part of the header
CString sTo;
for (int i=0; i<GetNumberOfRecipients(TO); i++)
{
CSMTPAddress* pRecipient = GetRecipient(i, TO);
if (i)
sTo += _T(",");
ASSERT(pRecipient);
sTo += pRecipient->GetRegularFormat();
}
//Create the "Cc:" part of the header
CString sCc;
for (i=0; i<GetNumberOfRecipients(CC); i++)
{
CSMTPAddress* pRecipient = GetRecipient(i, CC);
if (i)
sCc += _T(",");
ASSERT(pRecipient);
sCc += pRecipient->GetRegularFormat();
}
//No Bcc info added in header
//Add the From and to fields
CString sReply;
sReply.Format(_T("From: %s\r\nTo: %s\r\n"), HeaderEncode(m_From.GetRegularFormat()), HeaderEncode(sTo));
CString sBuf(sReply);
//Add the CC field if there is any
if (sCc.GetLength())
{
sReply.Format(_T("Cc: %s\r\n"), HeaderEncode(sCc));
sBuf += sReply;
}
//Add the subject, Date and X-Mailer fields
sReply.Format(_T("Subject: %s\r\nDate: %s\r\nX-Mailer: %s\r\n"), HeaderEncode(m_sSubject), HeaderEncode(sDate), HeaderEncode(m_sXMailer));
sBuf += sReply;
//Add the Mime header if needed
BOOL bHasChildParts = (m_RootPart.GetNumberOfChildBodyParts() != 0);
if (bHasChildParts && m_bMime)
{
sReply.Format(_T("MIME-Version: 1.0\r\nContent-Type: %s; boundary=\"%s\"\r\n"), m_RootPart.GetContentType(), m_RootPart.GetBoundary());
sBuf += sReply;
}
else if (!bHasChildParts && m_bMime)
{
sReply.Format(_T("MIME-Version: 1.0\r\nContent-Type: %s\r\n"), m_RootPart.GetContentType());
sBuf += sReply;
}
sBuf += _T("Content-Transfer-Encoding: quoted-printable\r\n");
//Add the optional Reply-To Field
if (m_ReplyTo.m_sEmailAddress.GetLength())
{
CString sReply;
sReply.Format(_T("Reply-To: %s\r\n"), m_ReplyTo.GetRegularFormat());
sBuf += sReply;
}
//Add the custom headers
int nCustomHeaders = m_CustomHeaders.GetSize();
for (i=0; i<nCustomHeaders; i++)
{
CString sHeader = m_CustomHeaders.GetAt(i);
sBuf += sHeader;
//Add line separators for each header bar the final one
if (i < (nCustomHeaders-1))
sBuf += _T("\r\n");
}
//Add the line separator between the header and what will follow
//i.e. the body
sBuf += _T("\r\n");
// restore original locale
_tsetlocale(LC_TIME, sOldLocale);
//Return the result
return sBuf;
}
//Converts header text to its encoded form according to RFC 2047
CString CSMTPMessage::HeaderEncode(const CString& sText) const
{
int nSize = sText.GetLength();
//Determine if a translation is needed
BOOL bTranslationNeeded = FALSE;
for (int i=0; i<nSize && !bTranslationNeeded; i++)
{
BYTE c = (BYTE) sText[i];
bTranslationNeeded = (c > 127);
}
CString sOut;
if (bTranslationNeeded)
{
sOut.Format(_T("=?%s?q?"), m_RootPart.GetCharset());
for (i=0; i<nSize; i++)
{
BYTE c = (BYTE) sText[i];
if (c == ' ') // A space
sOut += _T('_');
else if ((c > 127) || (c == '=') || (c == '?') || (c == '_'))
{
//Must Quote the text
sOut += _T('=');
sOut += CSMTPBodyPart::HexDigit((c & 0xF0) >> 4);
sOut += CSMTPBodyPart::HexDigit(c & 0x0F);
}
else
sOut += TCHAR(c);
}
sOut += _T("?=");
}
else
{
//Just pass the text thro unmodified
sOut = sText;
}
return sOut;
}
CSMTPAddressArray* CSMTPMessage::ParseMultipleRecipients(const CString& sRecipients)
{
ASSERT(sRecipients.GetLength()); //An empty string is now allowed
//What will be the return value
CSMTPAddressArray* pRecipients = new CSMTPAddressArray;
//Loop through the whole string, adding recipients as they are encountered
int length = sRecipients.GetLength();
TCHAR* buf = new TCHAR[length + 1]; // Allocate a work area (don't touch parameter itself)
_tcscpy(buf, sRecipients);
for (int pos=0, start=0; pos<=length; pos++)
{
//Valid separators between addresses are ',' or ';'
if ((buf[pos] == _T(',')) || (buf[pos] == _T(';')) || (buf[pos] == 0))
{
buf[pos] = 0; //Redundant when at the end of string, but who cares.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -