1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468 |
- #include "Smtp.h"
- CSmtpMessageBody::CSmtpMessageBody(LPCTSTR pszBody, LPCTSTR pszEncoding, LPCTSTR pszCharset, EncodingEnum encode)
- {
-
-
- if (pszEncoding) Encoding = pszEncoding;
- if (pszCharset) Charset = pszCharset;
- if (pszBody) Data = pszBody;
- TransferEncoding = encode;
- }
- const CSmtpMessageBody& CSmtpMessageBody::operator=(LPCTSTR pszBody)
- {
- Data = pszBody;
- return *this;
- }
- const CSmtpMessageBody& CSmtpMessageBody::operator=(const String& strBody)
- {
- Data = strBody;
- return *this;
- }
- CSmtpAttachment::CSmtpAttachment(LPCTSTR pszFilename, LPCTSTR pszAltName, BOOL bIsInline, LPCTSTR pszEncoding, LPCTSTR pszCharset, EncodingEnum encode)
- {
- if (pszFilename) FileName = pszFilename;
- if (pszAltName) AltName = pszAltName;
- if (pszEncoding) Encoding = pszEncoding;
- if (pszCharset) Charset = pszCharset;
- TransferEncoding = encode;
- Inline = bIsInline;
- }
- const CSmtpAttachment& CSmtpAttachment::operator=(LPCTSTR pszFilename)
- {
- FileName = pszFilename;
- return *this;
- }
- const CSmtpAttachment& CSmtpAttachment::operator=(const String& strFilename)
- {
- FileName = strFilename;
- return *this;
- }
- CSmtpAddress::CSmtpAddress(LPCTSTR pszAddress, LPCTSTR pszName)
- {
- if (pszAddress) Address = pszAddress;
- if (pszName) Name = pszName;
- }
- const CSmtpAddress& CSmtpAddress::operator=(LPCTSTR pszAddress)
- {
- Address = pszAddress;
- return *this;
- }
- const CSmtpAddress& CSmtpAddress::operator=(const String& strAddress)
- {
- Address = strAddress;
- return *this;
- }
- CSmtpMessage::CSmtpMessage()
- {
- TIME_ZONE_INFORMATION tzi;
- DWORD dwRet;
- long Offset;
-
- GetLocalTime(&Timestamp);
- GMTOffset = 0;
- dwRet = GetTimeZoneInformation(&tzi);
- Offset = tzi.Bias;
- if (dwRet == TIME_ZONE_ID_STANDARD) Offset += tzi.StandardBias;
- if (dwRet == TIME_ZONE_ID_DAYLIGHT) Offset += tzi.DaylightBias;
- GMTOffset = -((Offset / 60) * 100 + (Offset % 60));
- MimeType = mimeGuess;
- }
- void CSmtpMessage::CommitHeaders()
- {
- TCHAR szTime[64] = {0};
- TCHAR szDate[64] = {0};
- TCHAR szOut[1024] = {0};
- String strHeader;
- String strValue;
- int n;
-
- strHeader = _T("X-Priority");
- strValue = _T("3 (Normal)");
-
- if (Headers.FindKey(strHeader) == -1) Headers.Add(strHeader,strValue);
-
- strHeader = _T("X-MSMail-Priority");
- strValue = _T("Normal");
- if (Headers.FindKey(strHeader) == -1) Headers.Add(strHeader,strValue);
-
- strHeader = _T("X-Mailer");
- strValue = _T("ATL CSmtp Class Mailer by Robert Simpson (robert@blackcastlesoft.com)");
- if (Headers.FindKey(strHeader) == -1) Headers.Add(strHeader,strValue);
-
- strHeader = _T("Importance");
- strValue = _T("Normal");
- if (Headers.FindKey(strHeader) == -1) Headers.Add(strHeader,strValue);
-
- GetDateFormat(MAKELCID(LANG_ENGLISH, SORT_DEFAULT),0,&Timestamp,_T("ddd, d MMM yyyy"),szDate,64);
- GetTimeFormat(MAKELCID(LANG_ENGLISH, SORT_DEFAULT),0,&Timestamp,_T("H:mm:ss"),szTime,64);
-
-
- wsprintf(szOut,_T("%s %s %c%4.4d"),szDate,szTime,(GMTOffset>0)?'+':'-',GMTOffset);
-
- strHeader = _T("Date");
- strValue = szOut;
- Headers.Remove(strHeader);
- Headers.Add(strHeader,strValue);
-
- strHeader = _T("Subject");
- strValue = Subject;
- Headers.Remove(strHeader);
- Headers.Add(strHeader,strValue);
-
- strValue.erase();
- strHeader = _T("To");
- if (Recipient.Name.length())
- {
- wsprintf(szOut,_T("\"%s\" "),Recipient.Name.c_str());
- strValue += szOut;
- }
- if (Recipient.Address.length())
- {
- wsprintf(szOut,_T("<%s>"),Recipient.Address.c_str());
- strValue += szOut;
- }
-
- for (n = 0;n < CC.GetSize();n++)
- {
- if (strValue.length()) strValue += _T(",\r\n\t");
- if (CC[n].Name.length())
- {
- wsprintf(szOut,_T("\"%s\" "),CC[n].Name.c_str());
- strValue += szOut;
- }
- wsprintf(szOut,_T("<%s>"),CC[n].Address.c_str());
- strValue += szOut;
- }
- Headers.Remove(strHeader);
- Headers.Add(strHeader,strValue);
-
- strValue.erase();
- strHeader = _T("From");
- if (Sender.Name.length())
- {
- wsprintf(szOut,_T("\"%s\" "),Sender.Name.c_str());
- strValue += szOut;
- }
- wsprintf(szOut,_T("<%s>"),Sender.Address.c_str());
- strValue += szOut;
- Headers.Remove(strHeader);
- Headers.Add(strHeader,strValue);
- }
- void CSmtpMessage::Parse(String& strDest)
- {
- String strHeader;
- String strValue;
- String strTemp;
- String strBoundary;
- String strInnerBoundary;
- TCHAR szOut[1024];
- int n;
- strDest.erase();
-
- n = Message.GetSize();
- n += Attachments.GetSize();
-
- strHeader = _T("Content-Type");
- Headers.Remove(strHeader);
-
- if (n > 1)
- {
- wsprintf(szOut,_T("CSmtpMsgPart123X456_000_%8.8X"),GetTickCount());
- strBoundary = szOut;
- lstrcpy(szOut,_T("multipart/"));
- if (MimeType == mimeGuess)
- {
- if (Attachments.GetSize() == 0) MimeType = mimeAlternative;
- else MimeType = mimeMixed;
- }
- switch(MimeType)
- {
- case mimeAlternative:
- lstrcat(szOut,_T("alternative"));
- break;
- case mimeMixed:
- lstrcat(szOut,_T("mixed"));
- break;
- case mimeRelated:
- lstrcat(szOut,_T("related"));
- break;
- }
- lstrcat(szOut,_T(";\r\n\tboundary=\""));
- lstrcat(szOut,strBoundary.c_str());
- lstrcat(szOut,_T("\""));
- strValue = szOut;
- Headers.Add(strHeader,strValue);
- }
- strHeader = _T("MIME-Version");
- strValue = MIME_VERSION;
- Headers.Remove(strHeader);
- Headers.Add(strHeader,strValue);
-
- strHeader = _T("Message-ID");
- Headers.Remove(strHeader);
- if (MessageId.length())
- {
- wsprintf(szOut,_T("<%s>"),MessageId.c_str());
- strValue = szOut;
- Headers.Add(strHeader,strValue);
- }
-
- CommitHeaders();
-
- for (n = Headers.GetSize();n > 0;n--)
- {
- wsprintf(szOut,_T("%s: %s\r\n"),Headers.GetKeyAt(n-1).c_str(),Headers.GetValueAt(n-1).c_str());
- strDest += szOut;
- }
- if (strBoundary.length())
- {
- wsprintf(szOut,_T("\r\n%s\r\n"),MULTIPART_MESSAGE);
- strDest += szOut;
- }
-
-
-
- if (Attachments.GetSize() && Message.GetSize() > 1 && strBoundary.length())
- {
- wsprintf(szOut,_T("CSmtpMsgPart123X456_001_%8.8X"),GetTickCount());
- strInnerBoundary = szOut;
-
- wsprintf(szOut,_T("\r\n--%s\r\nContent-Type: multipart/alternative;\r\n\tboundary=\"%s\"\r\n"),strBoundary.c_str(),strInnerBoundary.c_str());
- strDest += szOut;
- }
- for (n = 0;n < Message.GetSize();n++)
- {
-
- if (strBoundary.length() || strInnerBoundary.length())
- {
- strDest += _T("\r\n--");
-
- if (strInnerBoundary.length()) strDest += strInnerBoundary;
- else strDest += strBoundary;
- strDest += _T("\r\n");
- }
- strValue.erase();
- strDest += _T("Content-Type: ");
- strDest += Message[n].Encoding;
-
- if (_tcsnicmp(Message[n].Encoding.c_str(),_T("text/"),5) == 0)
- {
- wsprintf(szOut,_T(";\r\n\tcharset=\"%s\""),Message[n].Charset.c_str());
- strDest += szOut;
- }
- strDest += _T("\r\n");
-
- strValue = Message[n].Data;
- EncodeMessage(Message[n].TransferEncoding,strValue,strTemp);
-
- strDest += _T("Content-Transfer-Encoding: ");
- strDest += strTemp;
-
-
- if (Message[n].ContentId.length())
- {
- wsprintf(szOut,_T("\r\nContent-ID: <%s>"),Message[n].ContentId.c_str());
- strDest += szOut;
- }
- strDest += _T("\r\n\r\n");
- strDest += strValue;
- }
-
- if (strInnerBoundary.length())
- {
- wsprintf(szOut,_T("\r\n--%s--\r\n"),strInnerBoundary.c_str());
- strDest += szOut;
- }
-
- for (n = 0;n < Attachments.GetSize();n++)
- {
- DWORD dwBytes = 0;
- CRegKey cKey;
- TCHAR szFilename[MAX_PATH] = {0};
-
- strValue = Attachments[n].FileName;
-
- lstrcpy(szFilename,strValue.c_str());
- HANDLE hFile = CreateFile(szFilename,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
- if (hFile != INVALID_HANDLE_VALUE)
- {
-
- DWORD dwSize = GetFileSize(hFile,NULL);
- LPBYTE pData = (LPBYTE)malloc(dwSize + 1);
- ZeroMemory(pData,dwSize+1);
- if (ReadFile(hFile,pData,dwSize,&dwBytes,NULL))
- {
-
- if (strBoundary.length())
- {
- wsprintf(szOut,_T("\r\n--%s\r\n"),strBoundary.c_str());
- strDest += szOut;
- }
-
- LPTSTR pszFile;
- if (!Attachments[n].AltName.length())
- {
-
- pszFile = _tcsrchr(szFilename,'\\');
- if (!pszFile) pszFile = szFilename;
- else pszFile ++;
- }
- else pszFile = (LPTSTR)Attachments[n].AltName.c_str();
-
- TCHAR szType[MAX_PATH] = {0};
- lstrcpy(szType,_T("application/octet-stream"));
-
- LPTSTR pszExt = _tcschr(pszFile,'.');
- if (pszExt)
- {
- if (!cKey.Open(HKEY_CLASSES_ROOT,pszExt,KEY_READ))
- {
- DWORD dwSize = MAX_PATH;
- cKey.QueryValue(_T("Content Type"), NULL, szType, &dwSize);
- cKey.Close();
- }
- }
-
- if (Attachments[n].Encoding.length())
- lstrcpy(szType,Attachments[n].Encoding.c_str());
-
- wsprintf(szOut,_T("Content-Type: %s"),szType);
- strDest += szOut;
-
- if (_tcsnicmp(szType,_T("text/"),5) == 0)
- {
- wsprintf(szOut,_T(";\r\n\tcharset=\"%s\""),Attachments[n].Charset.c_str());
- strDest += szOut;
- }
- wsprintf(szOut,_T(";\r\n\tname=\"%s\"\r\n"),pszFile);
- strDest += szOut;
-
- EncodeMessage(Attachments[n].TransferEncoding,strValue,strTemp,pData,dwSize);
-
- wsprintf(szOut,_T("Content-Transfer-Encoding: %s\r\n"),strTemp.c_str());
- strDest += szOut;
-
- strDest += _T("Content-Disposition: ");
-
- if (Attachments[n].Inline) strDest += _T("inline");
- else strDest += _T("attachment");
-
- strDest += _T(";\r\n\tfilename=\"");
- strDest += pszFile;
-
- if (Attachments[n].ContentId.length())
- {
- wsprintf(szOut,_T("\r\nContent-ID: <%s>"),Attachments[n].ContentId.c_str());
- strDest += szOut;
- }
- strDest += _T("\r\n\r\n");
-
- strDest += strValue;
- strTemp.erase();
- strValue.erase();
- }
-
- CloseHandle(hFile);
- free(pData);
- }
- }
-
- if (strBoundary.length())
- {
- wsprintf(szOut,_T("\r\n--%s--\r\n"),strBoundary.c_str());
- strDest += szOut;
- }
- }
- void CSmtpMessage::EncodeQuotedPrintable(String& strDest, String& strSrc)
- {
- String strTemp;
- String strTemp2;
- LPTSTR pszTok1;
- LPTSTR pszTok2;
- TCHAR szSub[16];
- TCHAR ch;
- int n;
- strDest.erase();
- if (!strSrc.length()) return;
-
- pszTok1 = (LPTSTR)strSrc.c_str();
- pszTok2 = pszTok1;
- do
- {
- if (*pszTok2 == '=' || *pszTok2 > 126 ||
- (*pszTok2 < 32 && (*pszTok2 != '\r' && *pszTok2 != '\n' && *pszTok2 != '\t')))
- {
- ch = *pszTok2;
- *pszTok2 = 0;
- strTemp += pszTok1;
- *pszTok2 = ch;
- wsprintf(szSub,_T("=%2.2X"),(BYTE)*pszTok2);
- strTemp += szSub;
- pszTok1 = pszTok2 + 1;
- }
- pszTok2 ++;
- } while (pszTok2 && *pszTok2);
-
- if (_tcslen(pszTok1)) strTemp += pszTok1;
- pszTok1 = (LPTSTR)strTemp.c_str();
- while (pszTok1)
- {
- pszTok2 = _tcschr(pszTok1,'\r');
- if (pszTok2) *pszTok2 = 0;
- while (1)
- {
- if (_tcslen(pszTok1) > 76)
- {
- n = 75;
- if (pszTok1[n-1] == '=') n -= 1;
- else if (pszTok1[n-2] == '=') n -= 2;
-
-
- ch = pszTok1[n];
- pszTok1[n] = 0;
- strDest += pszTok1;
- pszTok1[n] = ch;
- strDest += _T("=\r\n");
- pszTok1 += n;
- }
- else
- {
- n = (int)_tcslen(pszTok1);
- if (n)
- {
- if (pszTok1[n-1] == ' ' || pszTok1[n-1] == '\t')
- {
- wsprintf(szSub,_T("=%2.2X"),(BYTE)pszTok1[n-1]);
-
- pszTok1[n-1] = 0;
- strTemp2 = pszTok1;
- strTemp2 += szSub;
-
- pszTok1 = (LPTSTR)strTemp2.c_str();
- }
- else
- {
- strDest += pszTok1;
- if (pszTok2) strDest += _T("\r\n");
- break;
- }
- }
- else
- {
- if (pszTok2) strDest += _T("\r\n");
- break;
- }
- }
- }
- if (pszTok2)
- {
- *pszTok2 = '\r';
- pszTok2 ++;
- if (*pszTok2 == '\n') pszTok2 ++;
- }
- pszTok1 = pszTok2;
- }
- }
- void CSmtpMessage::BreakMessage(String& strDest, String& strSrc, int nLength)
- {
- String strTemp = strSrc;
- LPTSTR pszTok1;
- LPTSTR pszTok2;
- LPTSTR pszBreak;
- LPTSTR pszBreaks = _T(" -;.,?!");
- TCHAR ch;
- int nLen;
- strDest.erase();
- if (!strSrc.length()) return;
- nLen = (int)strTemp.length();
- nLen += (nLen / 60) * 2;
- strDest.reserve(nLen);
-
- pszTok1 = (LPTSTR)strTemp.c_str();
- while (pszTok1)
- {
- pszTok2 = _tcschr(pszTok1,'\r');
- if (pszTok2) *pszTok2 = 0;
- BOOL bNoBreaks = (!_tcspbrk(pszTok1,pszBreaks));
- nLen = (int)_tcslen(pszTok1);
- while (nLen > nLength)
- {
-
- pszBreak = &pszTok1[nLength - 1];
-
-
- if (!bNoBreaks)
- {
- while (!_tcschr(pszBreaks,*pszBreak) && pszBreak > pszTok1)
- pszBreak--;
- }
- pszBreak ++;
- ch = *pszBreak;
- *pszBreak = 0;
- strDest += pszTok1;
-
- strDest += _T("\r\n");
- *pszBreak = ch;
-
- nLen -= (int)(pszBreak - pszTok1);
-
- pszTok1 = pszBreak;
- }
- strDest += pszTok1;
- if (pszTok2)
- {
- strDest += _T("\r\n");
- *pszTok2 = '\r';
- pszTok2 ++;
- if (*pszTok2 == '\n') pszTok2 ++;
- }
- pszTok1 = pszTok2;
- }
- }
- void CSmtpMessage::Make7Bit(String& strDest, String& strSrc)
- {
- LPTSTR pszTok;
- strDest = strSrc;
- pszTok = (LPTSTR)strDest.c_str();
- do
- {
-
- if (*pszTok > 126 || *pszTok < 0)
- *pszTok = '?';
- pszTok ++;
- } while (pszTok && *pszTok);
- }
- void CSmtpMessage::EncodeMessage(EncodingEnum code, String& strMsg, String& strMethod, LPBYTE pByte, DWORD dwSize)
- {
- String strTemp;
- LPTSTR pszTok1;
- LPTSTR pszTok2;
- LPSTR pszBuffer = NULL;
- DWORD dwStart = GetTickCount();
- if (!pByte)
- {
- pszBuffer = (LPSTR)malloc(strMsg.length() + 1);
- _T2A(pszBuffer,strMsg.c_str());
- pByte = (LPBYTE)pszBuffer;
- dwSize = (DWORD)strMsg.length();
- }
-
- if (code == encodeGuess) code = GuessEncoding(pByte, dwSize);
- switch(code)
- {
- case encodeQuotedPrintable:
- strMethod = _T("quoted-printable");
- pszTok1 = (LPTSTR)malloc((dwSize+1) * sizeof(TCHAR));
- _A2T(pszTok1,(LPSTR)pByte);
- strMsg = pszTok1;
- free(pszTok1);
-
- EncodeQuotedPrintable(strTemp, strMsg);
- break;
- case encodeBase64:
- strMethod = _T("base64");
- {
- CBase64 cvt;
- cvt.Encode(pByte, dwSize);
- LPSTR pszTemp = (LPSTR)cvt.EncodedMessage();
- pszTok1 = (LPTSTR)malloc((lstrlenA(pszTemp)+1) * sizeof(TCHAR));
- _A2T(pszTok1,pszTemp);
- }
- strMsg = pszTok1;
- free(pszTok1);
- BreakMessage(strTemp, strMsg);
- break;
- case encode7Bit:
- strMethod = _T("7bit");
- pszTok1 = (LPTSTR)malloc((dwSize+1) * sizeof(TCHAR));
- _A2T(pszTok1,(LPSTR)pByte);
- strMsg = pszTok1;
- free(pszTok1);
- Make7Bit(strTemp, strMsg);
- strMsg = strTemp;
- BreakMessage(strTemp, strMsg);
- break;
- case encode8Bit:
- strMethod = _T("8bit");
- pszTok1 = (LPTSTR)malloc((dwSize+1) * sizeof(TCHAR));
- _A2T(pszTok1,(LPSTR)pByte);
- strMsg = pszTok1;
- free(pszTok1);
- BreakMessage(strTemp, strMsg);
- break;
- }
- if (pszBuffer) free(pszBuffer);
- strMsg.erase();
-
- pszTok1 = (LPTSTR)strTemp.c_str();
- do
- {
- pszTok2 = _tcsstr(pszTok1,_T("\r\n."));
- if (pszTok2)
- {
- *pszTok2 = 0;
- strMsg += pszTok1;
- *pszTok2 = '\r';
- strMsg += _T("\r\n..");
- pszTok1 = pszTok2 + 3;
- }
- } while (pszTok2);
- strMsg += pszTok1;
- TCHAR szOut[MAX_PATH] = {0};
- wsprintf(szOut,_T("Encoding took %dms\n"),GetTickCount() - dwStart);
- OutputDebugString(szOut);
- }
- EncodingEnum CSmtpMessage::GuessEncoding(LPBYTE pByte, DWORD dwLen)
- {
- int n7Bit = 0;
- int n8Bit = 0;
- int nLineStart = 0;
- int nLinesOver76 = 0;
- int nLines = 0;
- DWORD n;
-
- for (n = 0;n < dwLen; n++)
- {
- if (pByte[n] > 126 || (pByte[n] < 32 && pByte[n] != '\t' && pByte[n] != '\r' && pByte[n] != '\n'))
- n8Bit ++;
- else n7Bit ++;
-
- if (pByte[n] == '\r')
- {
- nLines ++;
- nLineStart = (n - nLineStart) - 1;
- if (nLineStart > 76) nLinesOver76 ++;
- nLineStart = n + 1;
- }
- }
-
- if ((n7Bit * 100) / dwLen > 89)
- {
-
- if (!nLinesOver76)
- {
- if (!n8Bit) return encode7Bit;
- else return encode8Bit;
- }
- else return encodeQuotedPrintable;
- }
- return encodeBase64;
- }
- CSmtp::CSmtp()
- {
- LPSERVENT pEnt;
-
- m_bExtensions = TRUE;
- m_dwCmdTimeout = 30;
- m_hSocket = INVALID_SOCKET;
- m_bConnected = m_bUsingExtensions = FALSE;
-
- pEnt = getservbyname("SMTP","tcp");
- if (pEnt) m_wSmtpPort = pEnt->s_port;
- else m_wSmtpPort = htons(25);
- }
- CSmtp::~CSmtp()
- {
-
- Close();
- }
- BOOL CSmtp::Connect(LPTSTR pszServer)
- {
- SOCKADDR_IN addr;
- int nRet;
- CHAR szHost[MAX_PATH] = {0};
- _T2A(szHost,pszServer);
-
- Close();
- WORD wVersionRequested;
- WSADATA wsaData;
- wVersionRequested = MAKEWORD( 2, 1 );
- WSAStartup( wVersionRequested, &wsaData );
-
- addr.sin_family = AF_INET;
- addr.sin_port = m_wSmtpPort;
- addr.sin_addr.s_addr = inet_addr(szHost);
-
- if (addr.sin_addr.s_addr == INADDR_NONE)
- {
-
- LPHOSTENT pHost = gethostbyname(szHost);
- if (!pHost)
- {
- return FALSE;
- }
- addr.sin_addr.s_addr = *(LPDWORD)pHost->h_addr;
- }
-
-
- m_hSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- if (m_hSocket == INVALID_SOCKET) return FALSE;
-
- if (connect(m_hSocket,(LPSOCKADDR)&addr,sizeof(addr)) == SOCKET_ERROR)
- {
- Close();
- return FALSE;
- }
-
- nRet = SendCmd(NULL);
- if (nRet != 220)
- {
- RaiseError(nRet);
- Close();
- return FALSE;
- }
-
- if (SendHello())
- {
- Close();
- return FALSE;
- }
- return TRUE;
- }
- void CSmtp::Close()
- {
- if (m_hSocket != INVALID_SOCKET)
- {
-
- if (m_bConnected) SendQuitCmd();
-
- shutdown(m_hSocket,2);
- closesocket(m_hSocket);
- }
- m_hSocket = INVALID_SOCKET;
- }
- int CSmtp::SendCmd(LPTSTR pszCmd)
- {
- USES_CONVERSION;
- FD_SET set;
- TIMEVAL tv;
- int nRet = 0;
- DWORD dwTick;
- CHAR szResult[CMD_RESPONSE_SIZE] = {0};
- LPSTR pszPos;
- LPSTR pszTok;
- BOOL bReportProgress = FALSE;
- LPSTR pszBuff;
-
- ZeroMemory(szResult,CMD_RESPONSE_SIZE);
- FD_ZERO(&set);
-
- if (pszCmd)
- {
- pszBuff = (LPSTR)malloc(lstrlen(pszCmd)+1);
- _T2A(pszBuff,pszCmd);
-
-
- nRet = 1;
- while (nRet > 0)
- {
- FD_SET(m_hSocket,&set);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- nRet = select(1,&set,NULL,NULL,&tv);
- if (nRet == 1) nRet = recv(m_hSocket,szResult,CMD_RESPONSE_SIZE,0);
- }
- DWORD dwPosition = 0;
- DWORD dwLen = lstrlen(pszCmd);
- if (dwLen > CMD_BLOCK_SIZE) bReportProgress = TRUE;
- while (dwLen != dwPosition)
- {
- DWORD dwMax = min(CMD_BLOCK_SIZE,dwLen - dwPosition);
- nRet = send(m_hSocket,&pszBuff[dwPosition],dwMax,0);
- if (nRet == SOCKET_ERROR)
- {
- free(pszBuff);
- return nRet;
- }
- dwPosition += dwMax;
- if (bReportProgress)
- {
- if (!SmtpProgress(pszBuff,dwPosition,dwLen))
- {
- free(pszBuff);
- return -1;
- }
- }
- }
-
- FD_ZERO(&set);
- FD_SET(m_hSocket,&set);
- nRet = select(1,NULL,&set,NULL,NULL);
- free(pszBuff);
- }
-
- ZeroMemory(szResult,CMD_RESPONSE_SIZE);
- pszPos = szResult;
-
- dwTick = GetTickCount();
- while (GetTickCount() - dwTick < (m_dwCmdTimeout * 1000))
- {
- FD_SET(m_hSocket,&set);
-
- tv.tv_sec = m_dwCmdTimeout - ((GetTickCount() - dwTick) / 1000);
- tv.tv_usec = 0;
-
- nRet = select(1,&set,NULL,NULL,&tv);
- if (nRet == SOCKET_ERROR) break;
-
- if (nRet == 1)
- {
- nRet = recv(m_hSocket,pszPos,CMD_RESPONSE_SIZE - (int)(pszPos - szResult),0);
-
- if (nRet == 0) nRet = SOCKET_ERROR;
- if (nRet == SOCKET_ERROR) break;
-
-
- pszPos += nRet;
- pszTok = strrchr(szResult,'\n');
- if (pszTok)
- {
-
- pszTok --;
- pszTok[0] = 0;
- break;
- }
- }
- }
-
- m_strResult = A2CT(szResult);
-
- if (nRet && nRet != SOCKET_ERROR)
- {
- szResult[3] = 0;
- nRet = atoi(szResult);
- SmtpCommandResponse(pszCmd, nRet, (LPTSTR)m_strResult.c_str());
- }
- else nRet = -1;
- return nRet;
- }
- int CSmtp::SmtpError(int , LPTSTR pszErr)
- {
- #ifdef _DEBUG
- if (pszErr)
- {
- OutputDebugString(_T("SmtpError: "));
- OutputDebugString(pszErr);
- OutputDebugString(_T("\n"));
- }
- #endif
- return 0;
- }
- int CSmtp::SmtpWarning(int , LPTSTR pszWarning)
- {
- #ifdef _DEBUG
- if (pszWarning)
- {
- OutputDebugString(_T("SmtpWarning: "));
- OutputDebugString(pszWarning);
- OutputDebugString(_T("\n"));
- }
- #endif
- return 0;
- }
- void CSmtp::SmtpCommandResponse(LPTSTR pszCmd, int , LPTSTR pszResponse)
- {
- #ifdef _DEBUG
- if (pszCmd)
- {
- TCHAR szOut[MAX_PATH+1] = {0};
- OutputDebugString(_T("SmtpCommand : "));
- while (lstrlen(pszCmd) > MAX_PATH)
- {
- lstrcpyn(szOut,pszCmd,MAX_PATH+1);
- OutputDebugString(szOut);
- Sleep(100);
- pszCmd += MAX_PATH;
- }
- OutputDebugString(pszCmd);
- }
- OutputDebugString(_T("SmtpResponse: "));
- OutputDebugString(pszResponse);
- OutputDebugString(_T("\n"));
- #endif
- }
- BOOL CSmtp::SmtpProgress(LPSTR , DWORD , DWORD )
- {
- return TRUE;
- }
- int CSmtp::RaiseError(int nError)
- {
-
-
- if (nError == -1) m_bConnected = FALSE;
- return SmtpError(nError, (LPTSTR)m_strResult.c_str());
- }
- int CSmtp::RaiseWarning(int nWarning)
- {
- return SmtpWarning(nWarning, (LPTSTR)m_strResult.c_str());
- }
- int CSmtp::SendMessage(CSmtpMessage &msg)
- {
- int nRet;
- int n;
- int nRecipientCount = 0;
-
- if (!msg.Sender.Address.length()) return -1;
-
-
- if (!msg.Recipient.Address.length() && !msg.CC.GetSize()) return -1;
-
-
-
-
- nRet = SendFrom((LPTSTR)msg.Sender.Address.c_str());
- if (nRet) return nRet;
-
- nRecipientCount = 0;
- if (msg.Recipient.Address.length())
- {
- nRet = SendTo((LPTSTR)msg.Recipient.Address.c_str());
- if (!nRet) nRecipientCount ++;
- }
-
- for (n = 0;n < msg.CC.GetSize();n++)
- {
- nRet = SendTo((LPTSTR)msg.CC[n].Address.c_str());
- if (!nRet) nRecipientCount ++;
- }
-
- for (n = 0;n < msg.BCC.GetSize();n++)
- {
- nRet = SendTo((LPTSTR)msg.BCC[n].Address.c_str());
- if (!nRet) nRecipientCount ++;
- }
-
- if (!nRecipientCount)
- RaiseError(nRet);
- else
- nRet = SendData(msg);
- return nRet;
- }
- int CSmtp::SendMessage(CSmtpAddress &addrFrom, CSmtpAddress &addrTo, LPCTSTR pszSubject, LPTSTR pszMessage, LPVOID pvAttachments, DWORD dwAttachmentCount)
- {
- CSmtpMessage message;
- CSmtpMessageBody body;
- CSmtpAttachment attach;
- body = pszMessage;
- message.Sender = addrFrom;
- message.Recipient = addrTo;
- message.Message.Add(body);
- message.Subject = pszSubject;
-
-
-
-
- if (!dwAttachmentCount && pvAttachments)
- {
- LPTSTR pszAttachments = (LPTSTR)pvAttachments;
- while (lstrlen(pszAttachments))
- {
- attach.FileName = pszAttachments;
- message.Attachments.Add(attach);
- pszAttachments = &pszAttachments[lstrlen(pszAttachments)];
- }
- }
-
-
- if (pvAttachments && dwAttachmentCount)
- {
- LPTSTR *ppszAttachments = (LPTSTR *)pvAttachments;
- while (dwAttachmentCount-- && ppszAttachments)
- {
- attach.FileName = ppszAttachments[dwAttachmentCount];
- message.Attachments.Add(attach);
- }
- }
- return SendMessage(message);
- }
- int CSmtp::SendMessage(LPTSTR pszAddrFrom, LPTSTR pszAddrTo, LPTSTR pszSubject, LPTSTR pszMessage, LPVOID pvAttachments, DWORD dwAttachmentCount)
- {
- CSmtpAddress addrFrom(pszAddrFrom);
- CSmtpAddress addrTo(pszAddrTo);
- return SendMessage(addrFrom,addrTo,pszSubject,pszMessage,pvAttachments,dwAttachmentCount);
- }
- int CSmtp::SendQuitCmd()
- {
- int nRet;
- if (!m_bConnected) return 0;
- nRet = SendCmd(_T("QUIT\r\n"));
- if (nRet != 221) RaiseError(nRet);
- m_bConnected = FALSE;
- return (nRet == 221) ? 0:nRet;
- }
- int CSmtp::SendHello()
- {
- int nRet = 0;
- TCHAR szName[64] = {0};
- TCHAR szMsg[MAX_PATH] = {0};
- DWORD dwSize = 64;
- GetComputerName(szName,&dwSize);
-
- wsprintf(szMsg,_T("EHLO %s\r\n"),szName);
- if (m_bExtensions) nRet = SendCmd(szMsg);
-
- if (nRet != 250)
- {
- m_bUsingExtensions = FALSE;
- szMsg[0] = 'H';
- szMsg[1] = 'E';
- nRet = SendCmd(szMsg);
- }
- else m_bUsingExtensions = TRUE;
-
- if (nRet != 250)
- {
- RaiseError(nRet);
- return nRet;
- }
-
- m_bConnected = TRUE;
-
-
- if (m_bUsingExtensions) SendAuthentication();
- return 0;
- }
- int CSmtp::SendAuthentication()
- {
- USES_CONVERSION;
- int nRet = 0;
- CBase64 cvt;
- LPCSTR pszTemp;
- TCHAR szMsg[MAX_PATH] = {0};
- CHAR szAuthType[MAX_PATH] = {0};
-
- while(1)
- {
-
- if (!m_strUser.length()) return 0;
-
-
- nRet = SendCmd(_T("AUTH LOGIN\r\n"));
-
- if (nRet != 334)
- {
- RaiseWarning(nRet);
- return nRet;
- }
-
-
-
-
- while (1)
- {
-
- _T2A(szAuthType,&(m_strResult.c_str())[4]);
- cvt.Decode(szAuthType);
- pszTemp = cvt.DecodedMessage();
-
- if (!lstrcmpiA(pszTemp,"Username:"))
- cvt.Encode(T2CA(m_strUser.c_str()));
- else if (!lstrcmpiA(pszTemp,"Password:"))
- cvt.Encode(T2CA(m_strPass.c_str()));
- else break;
-
- wsprintf(szMsg,_T("%s\r\n"),A2CT(cvt.EncodedMessage()));
- nRet = SendCmd(szMsg);
-
-
-
- if (nRet == 535)
- {
-
- nRet = RaiseWarning(nRet);
- if (!nRet)
- {
-
- nRet = 535;
- break;
- }
- }
-
- if (nRet != 334) break;
- }
-
- if (nRet != TRUE) break;
- }
-
- if (nRet != 235) RaiseError(nRet);
- return (nRet == 235) ? 0:nRet;
- }
- int CSmtp::SendFrom(LPTSTR pszFrom)
- {
- int nRet = 0;
- TCHAR szMsg[MAX_PATH] = {0};
- wsprintf(szMsg,_T("MAIL FROM: <%s>\r\n"),pszFrom);
-
- while (1)
- {
- nRet = SendCmd(szMsg);
-
- if (nRet == 530) nRet = SendAuthentication();
- else break;
- }
-
- if (nRet != 250) RaiseError(nRet);
- return (nRet == 250) ? 0:nRet;
- }
- int CSmtp::SendTo(LPTSTR pszTo)
- {
- int nRet;
- TCHAR szMsg[MAX_PATH] = {0};
-
- wsprintf(szMsg,_T("RCPT TO: <%s>\r\n"),pszTo);
- nRet = SendCmd(szMsg);
- if (nRet != 250 && nRet != 251) RaiseWarning(nRet);
- return (nRet == 250 || nRet == 251) ? 0:nRet;
- }
- int CSmtp::SendData(CSmtpMessage &msg)
- {
- int nRet;
- String strMsg;
-
- nRet = SendCmd(_T("DATA\r\n"));
- if (nRet != 354)
- {
- RaiseError(nRet);
- return nRet;
- }
-
- msg.Parse(strMsg);
- strMsg += _T("\r\n.\r\n");
-
- nRet = SendCmd((LPTSTR)strMsg.c_str());
- if (nRet != 250) RaiseError(nRet);
-
- return (nRet == 250) ? 0:nRet;
- }
|