📄 smtp.cpp
字号:
pszOut[nOutPos++] = *cp++;
if (*cp)
pszOut[nOutPos++] = *cp;
break;
}
case 1:
{
int c1 = pszIn[nInPos] & 0xFF;
pszOut[nOutPos++] = m_base64tab[(c1 & 0xFC) >> 2];
pszOut[nOutPos++] = m_base64tab[((c1 & 0x03) << 4)];
pszOut[nOutPos++] = '=';
pszOut[nOutPos++] = '=';
cp = EOL;
pszOut[nOutPos++] = *cp++;
if (*cp)
pszOut[nOutPos++] = *cp;
break;
}
case 2:
{
int c1 = pszIn[nInPos++] & 0xFF;
int c2 = pszIn[nInPos] & 0xFF;
pszOut[nOutPos++] = m_base64tab[(c1 & 0xFC) >> 2];
pszOut[nOutPos++] = m_base64tab[((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4)];
pszOut[nOutPos++] = m_base64tab[((c2 & 0x0F) << 2)];
pszOut[nOutPos++] = '=';
cp = EOL;
pszOut[nOutPos++] = *cp++;
if (*cp)
pszOut[nOutPos++] = *cp;
break;
}
default:
{
ASSERT(FALSE);
break;
}
}
pszOut[nOutPos] = 0;
*nOutLen = nOutPos;
return TRUE;
}
CSMTPMessage::CSMTPMessage() : m_sXMailer(_T("CSMTPConnection v1.3"))
{
}
CSMTPMessage::~CSMTPMessage()
{
}
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;
switch (RecipientType)
{
case TO: nIndex = m_ToRecipients.Add(recipient); break;
case CC: nIndex = m_CCRecipients.Add(recipient); break;
case BCC: nIndex = m_BCCRecipients.Add(recipient); break;
default: ASSERT(FALSE); break;
}
return nIndex;
}
void CSMTPMessage::RemoveRecipient(int nIndex, RECIPIENT_TYPE RecipientType)
{
switch (RecipientType)
{
case TO: m_ToRecipients.RemoveAt(nIndex); break;
case CC: m_CCRecipients.RemoveAt(nIndex); break;
case BCC: m_BCCRecipients.RemoveAt(nIndex); break;
default: ASSERT(FALSE); break;
}
}
CSMTPAddress CSMTPMessage::GetRecipient(int nIndex, RECIPIENT_TYPE RecipientType) const
{
CSMTPAddress address;
switch (RecipientType)
{
case TO: address = m_ToRecipients.GetAt(nIndex); break;
case CC: address = m_CCRecipients.GetAt(nIndex); break;
case BCC: address = m_BCCRecipients.GetAt(nIndex); break;
default: ASSERT(FALSE); break;
}
return address;
}
int CSMTPMessage::AddAttachment(CSMTPAttachment* pAttachment)
{
ASSERT(pAttachment->GetFilename().GetLength()); //an empty filename !
return m_Attachments.Add(pAttachment);
}
void CSMTPMessage::RemoveAttachment(int nIndex)
{
m_Attachments.RemoveAt(nIndex);
}
CSMTPAttachment* CSMTPMessage::GetAttachment(int nIndex) const
{
return m_Attachments.GetAt(nIndex);
}
int CSMTPMessage::GetNumberOfAttachments() const
{
return m_Attachments.GetSize();
}
CString CSMTPMessage::GetHeader() const
{
//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 recipient = GetRecipient(i, TO);
if (i)
sTo += _T(",");
sTo += recipient.GetRegularFormat();
}
//Create the "Cc:" part of the header
CString sCc;
for (i=0; i<GetNumberOfRecipients(CC); i++)
{
CSMTPAddress recipient = GetRecipient(i, CC);
if (i)
sCc += _T(",");
sCc += recipient.GetRegularFormat();
}
//No Bcc info added in header
//Stick everything together
CString sBuf;
if (sCc.GetLength())
sBuf.Format(_T("From: %s\r\n")\
_T("To: %s\r\n")\
_T("Cc: %s\r\n")\
_T("Subject: %s\r\n")\
_T("Date: %s\r\n")\
_T("X-Mailer: %s\r\n"),
m_From.GetRegularFormat(),
sTo,
sCc,
m_sSubject,
sDate,
m_sXMailer);
else
sBuf.Format(_T("From: %s\r\n")\
_T("To: %s\r\n")\
_T("Subject: %s\r\n")\
_T("Date: %s\r\n")\
_T("X-Mailer: %s\r\n"),
m_From.GetRegularFormat(),
sTo,
m_sSubject,
sDate,
m_sXMailer);
//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 optional fields if attachments are included
if (m_Attachments.GetSize())
sBuf += _T("MIME-Version: 1.0\r\nContent-type: multipart/mixed; boundary=\"#BOUNDARY#\"\r\n");
else
// avoid long textual message being automatically converted by the server:
sBuf += _T("MIME-Version: 1.0\r\nContent-type: text/plain; charset=US-ASCII\r\n");
sBuf += _T("\r\n");
//Return the result
return sBuf;
}
void CSMTPMessage::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;
}
}
void CSMTPMessage::AddBody(const CString& sBody)
{
m_sBody = sBody;
//Fix the case of a single dot on a line in the message body
FixSingleDot(m_sBody);
}
BOOL CSMTPMessage::AddMultipleRecipients(const CString& sRecipients, RECIPIENT_TYPE RecipientType)
{
ASSERT(sRecipients.GetLength()); //An empty string is now allowed
//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.
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"));
return FALSE;
}
// 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(_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())
AddRecipient(To, RecipientType);
//Move on to the next position
start = pos + 1;
}
}
delete[] buf;
return TRUE;
}
CSMTPConnection::CSMTPConnection()
{
m_bConnected = FALSE;
#ifdef _DEBUG
m_dwTimeout = 60000; //default timeout of 60 seconds when debugging
#else
m_dwTimeout = 2000; //default timeout of 2 seconds for normal release code
#endif
}
CSMTPConnection::~CSMTPConnection()
{
if (m_bConnected)
Disconnect();
}
BOOL CSMTPConnection::Connect(LPCTSTR pszHostName, int nPort)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//paramater validity checking
ASSERT(pszHostName);
//Create the socket
if (!m_SMTP.Create())
{
TRACE(_T("Failed to create client socket, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
//Connect to the SMTP Host
if (!m_SMTP.Connect(pszHostName, nPort))
{
TRACE(_T("Could not connect to the SMTP server %s on port %d, GetLastError returns: %d\n"), pszHostName, nPort, GetLastError());
return FALSE;
}
else
{
//We're now connected !!
m_bConnected = TRUE;
//check the response to the login
if (!ReadCommandResponse(220))
{
TRACE(_T("An unexpected SMTP login response was received\n"));
Disconnect();
return FALSE;
}
//retreive the localhost name
char sHostName[100];
gethostname(sHostName, sizeof(sHostName));
TCHAR* pszHostName = A2T(sHostName);
//Send the HELO command
CString sBuf;
sBuf.Format(_T("HELO %s\r\n"), pszHostName);
LPCSTR pszData = T2A((LPTSTR) (LPCTSTR) sBuf);
int nCmdLength = strlen(pszData);
if (!m_SMTP.Send(pszData, nCmdLength))
{
Disconnect();
TRACE(_T("An unexpected error occurred while sending the HELO command\n"));
return FALSE;
}
//check the response to the HELO command
if (!ReadCommandResponse(250))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -