📄 smtp.cpp
字号:
m_sFriendlyName(sFriendly), m_sEmailAddress(sAddress)
{
ASSERT(m_sEmailAddress.GetLength()); //An empty address is not allowed
}
CSMTPAddress& CSMTPAddress::operator=(const CSMTPAddress& r)
{
m_sFriendlyName = r.m_sFriendlyName;
m_sEmailAddress = r.m_sEmailAddress;
return *this;
}
CString CSMTPAddress::GetRegularFormat() const
{
ASSERT(m_sEmailAddress.GetLength()); //Email Address must be valid
CString sAddress;
if (m_sFriendlyName.IsEmpty())
sAddress = m_sEmailAddress; //Just transfer the address across directly
else
sAddress.Format(_T("%s <%s>"), m_sFriendlyName, m_sEmailAddress);
return sAddress;
}
CSMTPBodyPart::CSMTPBodyPart() : m_sCharset(_T("iso-8859-1")), m_sContentType(_T("text/plain")), m_pParentBodyPart(NULL), m_bQuotedPrintable(TRUE)
{
//Automatically generate a unique boundary separator for this body part by creating a guid
UUID uuid;
UuidCreate(&uuid);
//Convert it to a string
#ifdef _UNICODE
TCHAR* pszGuid = NULL;
#else
unsigned char* pszGuid = NULL;
#endif
UuidToString(&uuid, &pszGuid);
m_sBoundary = pszGuid;
//Free up the temp memory
RpcStringFree(&pszGuid);
}
CSMTPBodyPart::CSMTPBodyPart(const CSMTPBodyPart& bodyPart)
{
*this = bodyPart;
}
CSMTPBodyPart::~CSMTPBodyPart()
{
//Free up the array memory
for (int i=0; i<m_ChildBodyParts.GetSize(); i++)
delete m_ChildBodyParts.GetAt(i);
m_ChildBodyParts.RemoveAll();
}
CSMTPBodyPart& CSMTPBodyPart::operator=(const CSMTPBodyPart& bodyPart)
{
m_sFilename = bodyPart.m_sFilename;
m_sText = bodyPart.m_sText;
m_sTitle = bodyPart.m_sTitle;
m_sContentType = bodyPart.m_sContentType;
m_sCharset = bodyPart.m_sCharset;
m_sContentBase = bodyPart.m_sContentBase;
m_sContentID = bodyPart.m_sContentID;
m_sContentLocation = bodyPart.m_sContentLocation;
m_pParentBodyPart = bodyPart.m_pParentBodyPart;
m_sBoundary = bodyPart.m_sBoundary;
m_bQuotedPrintable = bodyPart.m_bQuotedPrintable;
//Free up the array memory
for (int i=0; i<m_ChildBodyParts.GetSize(); i++)
delete m_ChildBodyParts.GetAt(i);
m_ChildBodyParts.RemoveAll();
//Now copy over the new object
for (i=0; i<bodyPart.m_ChildBodyParts.GetSize(); i++)
{
CSMTPBodyPart* pBodyPart = new CSMTPBodyPart(*bodyPart.m_ChildBodyParts.GetAt(i));
pBodyPart->m_pParentBodyPart = this;
m_ChildBodyParts.Add(pBodyPart);
}
return *this;
}
BOOL CSMTPBodyPart::SetFilename(const CString& sFilename)
{
ASSERT(sFilename.GetLength()); //Empty Filename !
//determine the file size
CFileStatus fs;
if (!CFile::GetStatus(sFilename, fs))
{
TRACE(_T("Failed to get the status for file %s, probably does not exist\n"), m_sFilename);
return FALSE;
}
//Hive away the filename and form the title from the filename
TCHAR sPath[_MAX_PATH];
TCHAR sFname[_MAX_FNAME];
TCHAR sExt[_MAX_EXT];
_tsplitpath(sFilename, NULL, NULL, sFname, sExt);
_tmakepath(sPath, NULL, NULL, sFname, sExt);
m_sFilename = sFilename;
m_sTitle = sPath;
//Also sent the content type to be appropiate for an attachment
m_sContentType = _T("application/octet-stream");
return TRUE;
}
CString CSMTPBodyPart::Replace(const CString& sText, const CString& sToBeReplaced, const CString& sReplaceWith)
{
//The string we will be returning
CString sFind(sText);
CString sReturn;
int nFind = -1;
int nToBeReplacedLength = sToBeReplaced.GetLength();
do
{
nFind = sFind.Find(sToBeReplaced);
if (nFind != -1)
{
sReturn += (sFind.Left(nFind) + sReplaceWith);
sFind = sFind.Right(sFind.GetLength() - nFind - nToBeReplacedLength);
}
}
while (nFind != -1);
sReturn += sFind;
return sReturn;
}
void CSMTPBodyPart::SetText(const CString& sText)
{
m_sText = sText;
//Ensure lines are correctly wrapped
m_sText = Replace(m_sText, _T("\r\n"), _T("\n"));
m_sText = Replace(m_sText, _T("\r"), _T("\n"));
m_sText = Replace(m_sText, _T("\n"), _T("\r\n"));
//Fix the case of a single dot on a line in the message body
FixSingleDot(m_sText);
//Also set the content type while we are at it
m_sContentType = _T("text/plain");
}
void CSMTPBodyPart::SetContentID(const CString& sContentID)
{
m_sContentLocation.Empty();
m_sContentID = sContentID;
}
CString CSMTPBodyPart::GetContentID() const
{
return m_sContentID;
}
void CSMTPBodyPart::SetContentLocation(const CString& sContentLocation)
{
m_sContentID.Empty();
m_sContentLocation = sContentLocation;
}
CString CSMTPBodyPart::GetContentLocation() const
{
return m_sContentLocation;
}
char CSMTPBodyPart::HexDigit(int nDigit)
{
if (nDigit < 10)
return (char) (nDigit + '0');
else
return (char) (nDigit - 10 + 'A');
}
//Converts text to its Quoted printable equivalent according to RFC 2045
CString CSMTPBodyPart::QuotedPrintableEncode(const CString& sText)
{
CString sTemp;
int nSize = sText.GetLength();
for (int i=0; i<nSize; i++)
{
BYTE c = (BYTE) sText[i];
if (((c >= 33) && (c <= 60)) || ((c >= 62) && (c <= 126)) || (c == '\r') || (c == '\n') || (c == '\t') || (c == ' '))
sTemp += TCHAR(c);
else
{
//otherwise must quote the text
sTemp += _T('=');
sTemp += HexDigit((c & 0xF0) >> 4);
sTemp += HexDigit(c & 0x0F);
}
}
//Now insert soft line breaks where appropiate
CString sOut;
int nStartLine = 0;
int nLen = sTemp.GetLength();
for (i=0; i<nLen; i++)
{
BYTE c = (BYTE) sTemp[i];
if (c == '\n' || c == '\r' || i == (nLen-1))
{
sOut += sTemp.Mid(nStartLine, i-nStartLine+1);
nStartLine = i+1;
continue;
}
if ((i - nStartLine) > SMTP_MAXLINE)
{
BOOL bInWord = TRUE;
while (bInWord)
{
bInWord = (!isspace(c) && sTemp[i-2] != _T('='));
if (bInWord)
{
--i;
c = (BYTE) sTemp[i];
}
if (i == nStartLine)
{
i = nStartLine + SMTP_MAXLINE;
break;
}
}
sOut += sTemp.Mid(nStartLine, i-nStartLine+1);
sOut += _T("=\r\n");
nStartLine = i+1;
}
}
return sOut;
}
void CSMTPBodyPart::FreeHeader(LPSTR& pszHeader)
{
//The CSMTPBodyPart class always allocates the memory for the header
delete [] pszHeader;
pszHeader = NULL;
}
void CSMTPBodyPart::FreeBody(LPSTR& pszBody)
{
//The CSMTPBodyPart class allocates the memory for the body if it was not base 64 encoded
if (pszBody)
{
delete [] pszBody;
pszBody = NULL;
}
}
void CSMTPBodyPart::FreeFooter(LPSTR& pszFooter)
{
//The CSMTPBodyPart class always allocates the memory for the footer
delete [] pszFooter;
pszFooter = NULL;
}
BOOL CSMTPBodyPart::GetHeader(LPSTR& pszHeader, int& nHeaderSize)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//Assume the worst
BOOL bSuccess = FALSE;
CString sHeader;
if (m_sFilename.GetLength())
{
//Ok, it's a file
//Form the header to go along with this body part
if (GetNumberOfChildBodyParts())
sHeader.Format(_T("\r\n\r\n--%s\r\nContent-Type: %s; charset=%s; name=%s; Boundary=\"%s\"\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=%s\r\n"),
m_pParentBodyPart->m_sBoundary, m_sContentType, m_sCharset, m_sTitle, m_sBoundary, m_sTitle);
else
sHeader.Format(_T("\r\n\r\n--%s\r\nContent-Type: %s; charset=%s; name=%s\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=%s\r\n"),
m_pParentBodyPart->m_sBoundary, m_sContentType, m_sCharset, m_sTitle, m_sTitle);
bSuccess = TRUE;
}
else
{
//ok, it's some text
//Form the header to go along with this body part
ASSERT(m_pParentBodyPart);
if (GetNumberOfChildBodyParts())
{
if (m_bQuotedPrintable)
sHeader.Format(_T("\r\n--%s\r\nContent-Type: %s; charset=%s; Boundary=\"%s\"\r\nContent-Transfer-Encoding: quoted-printable\r\n"),
m_pParentBodyPart->m_sBoundary, m_sContentType, m_sCharset, m_sBoundary);
else
sHeader.Format(_T("\r\n--%s\r\nContent-Type: %s; charset=%s; Boundary=\"%s\"\r\n"),
m_pParentBodyPart->m_sBoundary, m_sContentType, m_sCharset, m_sBoundary);
}
else
{
if (m_bQuotedPrintable)
sHeader.Format(_T("\r\n--%s\r\nContent-Type: %s; charset=%s\r\nContent-Transfer-Encoding: quoted-printable\r\n"),
m_pParentBodyPart->m_sBoundary, m_sContentType, m_sCharset);
else
sHeader.Format(_T("\r\n--%s\r\nContent-Type: %s; charset=%s\r\n"),
m_pParentBodyPart->m_sBoundary, m_sContentType, m_sCharset);
}
bSuccess = TRUE;
}
//Add the other headers
if (m_sContentBase.GetLength())
{
CString sLine;
sLine.Format(_T("Content-Base: %s\r\n"), m_sContentBase);
sHeader += sLine;
}
if (m_sContentID.GetLength())
{
CString sLine;
sLine.Format(_T("Content-ID: %s\r\n"), m_sContentID);
sHeader += sLine;
}
if (m_sContentLocation.GetLength())
{
CString sLine;
sLine.Format(_T("Content-Location: %s\r\n"), m_sContentLocation);
sHeader += sLine;
}
sHeader += _T("\r\n");
nHeaderSize = _tcslen(sHeader);
pszHeader = new char[nHeaderSize+1];
strcpy(pszHeader, T2A((LPTSTR) (LPCTSTR) sHeader));
return bSuccess;
}
BOOL CSMTPBodyPart::GetBody(LPSTR& pszBody, int& nBodySize)
{
USES_CONVERSION;
BOOL bSuccess = FALSE;
if (m_sFilename.GetLength())
{
//如果是附件
//打开文件
CFile infile;
if (infile.Open(m_sFilename, CFile::modeRead | CFile::shareDenyWrite))
{
DWORD dwSize = infile.GetLength();
if (dwSize)
{
//读入数据
BYTE* pszIn = new BYTE[dwSize];
try
{
infile.Read(pszIn, dwSize);
bSuccess = TRUE;
}
catch(CFileException* pEx)
{
bSuccess = FALSE;
pEx->Delete();
}
if (bSuccess)
{
//编码
m_Coder.Encode(pszIn, dwSize);
//删除了输入缓冲区
delete [] pszIn;
//关闭输入文件
infile.Close();
//形成编码后的发送内容
LPSTR pszEncoded = m_Coder.EncodedMessage();
int nEncodedSize = m_Coder.EncodedMessageSize();
nBodySize = nEncodedSize + (((nEncodedSize/76)+1)*2) + 1;
pszBody = new char[nBodySize];
--nBodySize;
int nInPos = 0;
int nOutPos = 0;
while (nInPos < nEncodedSize)
{
int nThisLineSize = min(nEncodedSize - nInPos, SMTP_MAXLINE);
CopyMemory(&pszBody[nOutPos], &pszEncoded[nInPos], nThisLineSize);
nOutPos += nThisLineSize;
CopyMemory(&pszBody[nOutPos], "\r\n", 2);
nOutPos += 2;
nInPos += nThisLineSize;
}
pszBody[nOutPos] = '\0'; //以空字符串结束
}
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -