Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

765 lines
24 KiB

  1. //
  2. // WebCheck Mail Agent
  3. //
  4. // A user specifies that they are to be notified via email when a web checked
  5. // object (usually a page) changes.
  6. //
  7. // When the subscription is the delivery agent will call the mail agent upon completion
  8. // with a temporary ISubscriptionItem
  9. //
  10. // Julian Jiggins (julianj), January 8, 1997
  11. //
  12. #include "private.h"
  13. #include "mapi.h"
  14. #include "smtp.h"
  15. #include "mlang.h"
  16. #include <mluisupp.h>
  17. #undef TF_THISMODULE
  18. #define TF_THISMODULE TF_MAILAGENT
  19. //
  20. // Global strings
  21. // REVIEW move to a better place
  22. //
  23. #define MAIL_HANDLER TEXT("Software\\Clients\\Mail")
  24. #define MAIL_ATHENA TEXT("Internet Mail and News")
  25. #define SUBJECT_LINE TEXT("Subscription delivered")
  26. #define MESSAGE_PREFIX TEXT(" \r\nThe website you requested ")
  27. #define MESSAGE_SUFFIX TEXT(" has been delivered")
  28. #define ATHENA_SMTP_SERVER \
  29. TEXT("Software\\Microsoft\\Internet Mail and News\\Mail\\SMTP")
  30. #define NETSCAPE_SMTP_SERVER \
  31. TEXT("Software\\Netscape\\netscape Navigator\\Services\\SMTP_Server")
  32. #define EUDORA_COMMANDLINE TEXT("Software\\Qualcomm\\Eudora\\CommandLine")
  33. #define NOTE_TEXT_LENGTH 4096
  34. #define ENCODING_STRLEN 32
  35. //////////////////////////////////////////////////////////////////////////
  36. //
  37. // Email helper functions
  38. //
  39. //////////////////////////////////////////////////////////////////////////
  40. //
  41. // Returns a MemAlloc'd string with HTMLBreak inserted in place of '\d'.
  42. //
  43. void AddHTMLBreakText(LPSTR szText, LPSTR szHTMLBreak, LPSTR *lpHTMLText)
  44. {
  45. ASSERT(szText);
  46. ASSERT(szHTMLBreak);
  47. ASSERT(!*lpHTMLText);
  48. LPSTR lpTmp = NULL, lpTmp2 = NULL, lpHTMLAbstract = NULL;
  49. int cbCRs = 0;
  50. int cbLFs = 0;
  51. DWORD dwExtra = 0;
  52. //
  53. // Count number of carriage returns
  54. //
  55. for (lpTmp = szText; *lpTmp; lpTmp++)
  56. {
  57. if (*lpTmp == 0x0d)
  58. cbCRs++;
  59. if (*lpTmp == 0x0a)
  60. cbLFs++;
  61. }
  62. dwExtra = lstrlenA(szText) - cbCRs - cbLFs + cbCRs * lstrlenA(szHTMLBreak) + 1;
  63. //
  64. // Allocate appropriate size string
  65. //
  66. *lpHTMLText = lpHTMLAbstract = (LPSTR)MemAlloc(LPTR, dwExtra);
  67. if (!lpHTMLAbstract)
  68. return;
  69. //
  70. // Create new HTML abstract string.
  71. //
  72. for (lpTmp = szText; *lpTmp; lpTmp++)
  73. {
  74. if (*lpTmp == 0x0d)
  75. {
  76. for (lpTmp2 = szHTMLBreak; *lpTmp2; lpTmp2++, lpHTMLAbstract++)
  77. *lpHTMLAbstract = *lpTmp2;
  78. }
  79. else if (*lpTmp != 0x0a)
  80. {
  81. *lpHTMLAbstract = *lpTmp;
  82. lpHTMLAbstract++;
  83. }
  84. }
  85. *lpHTMLAbstract = '\0';
  86. }
  87. #ifdef DEBUG
  88. void DBG_OUTPUT_MAPI_ERROR(ULONG ul)
  89. {
  90. switch(ul)
  91. {
  92. case MAPI_E_LOGON_FAILURE:
  93. DBG("MailAgent: MAPI LOGON FAILURE"); break;
  94. case MAPI_E_FAILURE:
  95. DBG("MailAgent: MAPI_E_FAILURE"); break;
  96. default:
  97. DBG("MailAgent: Failed to send mail message"); break;
  98. }
  99. }
  100. #else
  101. #define DBG_OUTPUT_MAPI_ERROR(ul)
  102. #endif
  103. //
  104. // Build an HTML message containing a frameset that effectively inlines
  105. // the requested URL
  106. //
  107. BOOL BuildHTMLMessage(LPSTR szEmailAddress, LPSTR szName, LPSTR szURL,
  108. CHAR **ppHTMLMessage, LPSTR szTitle, LPSTR szAbstract,
  109. LPSTR szSrcCharset)
  110. {
  111. *ppHTMLMessage = NULL; // clear out parameter
  112. CHAR * lpBuffer = NULL;
  113. CHAR szWrapper[NOTE_TEXT_LENGTH];
  114. CHAR szMessageFormat[NOTE_TEXT_LENGTH];
  115. CHAR szMessageFormat2[NOTE_TEXT_LENGTH];
  116. CHAR szMessageText[NOTE_TEXT_LENGTH];
  117. CHAR szMessageHTML[NOTE_TEXT_LENGTH];
  118. CHAR szTextBreak[10];
  119. CHAR szHTMLBreak[10];
  120. //
  121. // Load the wrapper for the HTML message. This is the header stuff
  122. // and multipart MIME and HTML goop
  123. //
  124. int iRet = MLLoadStringA(IDS_AGNT_HTMLMESSAGEWRAPPER, szWrapper, NOTE_TEXT_LENGTH);
  125. ASSERT(iRet > 0);
  126. if (szTitle != NULL) {
  127. // NOTE: Size is probably slightly larger than necessary due to %1's.
  128. LPSTR lpHTMLAbstract = NULL, lpNewAbstract = NULL;
  129. DWORD dwTotalSize = 0;
  130. //
  131. // load string for single HTML line break as well as tag on for custom email
  132. //
  133. MLLoadStringA(IDS_AGNT_EMAILMESSAGE, szMessageText, ARRAYSIZE(szMessageText));
  134. MLLoadStringA(IDS_AGNT_HTMLBREAKSINGLE, szHTMLBreak, ARRAYSIZE(szHTMLBreak));
  135. //
  136. // Create new abstract string (szAbstract + email tagger)
  137. //
  138. dwTotalSize = lstrlenA(szAbstract) + lstrlenA(szMessageText) + 1;
  139. LPSTR szNewAbstract = (LPSTR)MemAlloc(LPTR, dwTotalSize * sizeof(CHAR));
  140. if (!szNewAbstract)
  141. return FALSE;
  142. lstrcpyA(szNewAbstract, szAbstract);
  143. StrCatA(szNewAbstract, szMessageText);
  144. AddHTMLBreakText(szNewAbstract, szHTMLBreak, &lpHTMLAbstract);
  145. if (!lpHTMLAbstract)
  146. {
  147. MemFree(szNewAbstract);
  148. return FALSE;
  149. }
  150. dwTotalSize = lstrlenA(szWrapper) + lstrlenA(szEmailAddress) +
  151. 2*lstrlenA(szTitle) + lstrlenA(szNewAbstract) + lstrlenA(szSrcCharset) +
  152. lstrlenA(lpHTMLAbstract) + lstrlenA(szURL) + 1;
  153. lpBuffer = (CHAR *)MemAlloc(LPTR, dwTotalSize * sizeof(CHAR));
  154. if (!lpBuffer)
  155. return FALSE;
  156. LPSTR lpArguments[6];
  157. lpArguments[0] = szEmailAddress;
  158. lpArguments[1] = szTitle;
  159. lpArguments[2] = szNewAbstract;
  160. lpArguments[3] = szSrcCharset; // the charset of the HTML page
  161. lpArguments[4] = szURL;
  162. lpArguments[5] = lpHTMLAbstract;
  163. //
  164. // Reason for FormatMessage is that wsprintf is limited up to 1024 bytes
  165. //
  166. FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  167. szWrapper, 0, 0, lpBuffer, dwTotalSize, (va_list *)&lpArguments[0]);
  168. MemFree(szNewAbstract);
  169. MemFree(lpHTMLAbstract);
  170. } else {
  171. //
  172. // Load line breaks for the plaintext and html messages
  173. //
  174. iRet = MLLoadStringA(IDS_AGNT_TEXTBREAK, szTextBreak, ARRAYSIZE(szTextBreak));
  175. ASSERT(iRet > 0);
  176. iRet = MLLoadStringA(IDS_AGNT_HTMLBREAK, szHTMLBreak, ARRAYSIZE(szHTMLBreak));
  177. ASSERT(iRet > 0);
  178. //
  179. // Load the actual text message to put sent
  180. //
  181. iRet = MLLoadStringA(IDS_AGNT_HTMLMESSAGETEXT, szMessageFormat, NOTE_TEXT_LENGTH);
  182. ASSERT(iRet > 0);
  183. iRet = MLLoadStringA(IDS_AGNT_HTMLMESSAGETEXT2, szMessageFormat2, NOTE_TEXT_LENGTH);
  184. ASSERT(iRet > 0);
  185. //
  186. // Insert the text messages into the wrapper. Note two message get
  187. // Once in the mime section for text/ascii and once in the
  188. // noframes section of the text/html frameset. This is a work around
  189. // for clients (like Outlook) that think they can render HTML
  190. // but cannot really.
  191. // The second message IDS_AGNT_HTMLMESSAGETEXT2 should NOT be localized
  192. // this is only going to be seen by Exchange users. In the future exchange
  193. // will handle html mail correct, so it acceptable that for example
  194. // Japanese Exchange users see english in this message. Most Japanese
  195. // users will user Outlook Express and so will just see the html message
  196. //
  197. // First we format 2 text messages, one for text and one for HTML,
  198. // since message itself is relatively small we know its < 1024 bytes
  199. iRet = wnsprintfA(szMessageText, ARRAYSIZE(szMessageText), szMessageFormat,
  200. szName, szTextBreak, szURL, szTextBreak);
  201. ASSERT(iRet > lstrlenA(szMessageFormat));
  202. iRet = wnsprintfA(szMessageHTML, ARRAYSIZE(szMessageHTML), szMessageFormat2,
  203. szName, szHTMLBreak, szURL, szHTMLBreak);
  204. ASSERT(iRet > lstrlenA(szMessageFormat2));
  205. DWORD dwTotalSize = lstrlenA(szWrapper) + lstrlenA(szEmailAddress) +
  206. lstrlenA(szName) + lstrlenA(szMessageText) + lstrlenA(szSrcCharset) +
  207. lstrlenA(szMessageHTML) + lstrlenA(szURL) + 1;
  208. lpBuffer = (CHAR *)MemAlloc(LPTR, dwTotalSize * sizeof(CHAR));
  209. if (!lpBuffer)
  210. return FALSE;
  211. LPSTR lpArguments[6];
  212. lpArguments[0] = szEmailAddress; // target email address
  213. lpArguments[1] = szName; // the name of the page that goes in the subject line
  214. lpArguments[2] = szMessageText; // the plain text message
  215. lpArguments[3] = szSrcCharset; // the charset of the HTML page
  216. lpArguments[4] = szURL; // the href of the page that goes in the frame set
  217. lpArguments[5] = szMessageHTML; // the plain text message that goes in the
  218. // noframes part of the frameset
  219. DWORD dwRet;
  220. dwRet = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  221. szWrapper, 0, 0, lpBuffer, dwTotalSize, (va_list *)&lpArguments[0]);
  222. ASSERT(dwRet);
  223. }
  224. *ppHTMLMessage = lpBuffer;
  225. return TRUE;
  226. }
  227. //
  228. // Build the actual text of the message to be sent via SMTP,
  229. // load format string from resource and insert URL and URL's friently name.
  230. //
  231. void BuildSMTPMessage(LPSTR szName, LPSTR szURL, LPSTR *szMessage,
  232. LPSTR szTitle, LPSTR szAbstract)
  233. {
  234. CHAR szFormatText[NOTE_TEXT_LENGTH];
  235. int i;
  236. ASSERT(szMessage);
  237. if (!szMessage)
  238. return;
  239. *szMessage = NULL;
  240. if (szTitle != NULL) {
  241. i = MLLoadStringA(IDS_AGNT_SMTPMESSAGE_OTHER, szFormatText, NOTE_TEXT_LENGTH);
  242. ASSERT(i != 0);
  243. DWORD dwLen = lstrlenA(szFormatText) + lstrlenA(szTitle) + lstrlenA(szAbstract) + 1;
  244. *szMessage = (LPSTR) MemAlloc(LPTR, dwLen * sizeof(CHAR));
  245. if (!*szMessage)
  246. return;
  247. LPSTR lpArgs[2];
  248. lpArgs[0] = szTitle;
  249. lpArgs[1] = szAbstract;
  250. FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  251. szFormatText, 0, 0, *szMessage, dwLen, (va_list *)&lpArgs[0]);
  252. } else {
  253. i = MLLoadStringA(IDS_AGNT_SMTPMESSAGE, szFormatText, NOTE_TEXT_LENGTH);
  254. ASSERT(i != 0);
  255. DWORD dwLen = lstrlenA(szFormatText) + 2*lstrlenA(szName) + lstrlenA(szURL) + 1;
  256. *szMessage = (LPSTR) MemAlloc(LPTR, dwLen * sizeof(CHAR));
  257. if (!*szMessage)
  258. return;
  259. LPSTR lpArgs[3];
  260. lpArgs[0] = lpArgs[1] = szName;
  261. lpArgs[2] = szURL;
  262. FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  263. szFormatText, 0, 0, *szMessage, dwLen, (va_list *)&lpArgs[0]);
  264. }
  265. }
  266. #if 0
  267. //
  268. // Build MAPI message structure
  269. //
  270. void BuildMAPIMessage(
  271. LPTSTR lpszName,
  272. LPTSTR lpszURL,
  273. LPTSTR lpszEmailAddress,
  274. MapiMessage * lpMessage,
  275. MapiRecipDesc * lpRecipient,
  276. LPTSTR lpszNoteText, // [out]
  277. LPTSTR lpszSubject, // [out]
  278. LPTSTR lpszTitle, // [in] title, NULL if not custom
  279. LPTSTR lpszAbstract) // [in] abstract, NULL if not custom
  280. {
  281. TCHAR szFmtNoteText[NOTE_TEXT_LENGTH];
  282. TCHAR szFmtSubject[INTERNET_MAX_URL_LENGTH];
  283. int i;
  284. //
  285. // zero out the passed in mapi structures
  286. //
  287. ZeroMemory(lpMessage, sizeof(MapiMessage));
  288. ZeroMemory(lpRecipient, sizeof(MapiRecipDesc));
  289. #error The wsprintf's below need to be converted to wnsprintf
  290. //
  291. // Load the strings containing the bulk of the email message
  292. //
  293. if (lpszTitle != NULL) {
  294. MLLoadString(IDS_AGNT_MAPIMESSAGE_OTHER, szFmtNoteText, NOTE_TEXT_LENGTH);
  295. MLLoadString(IDS_AGNT_MAPISUBJECT_OTHER, szFmtSubject, INTERNET_MAX_URL_LENGTH);
  296. i = wsprintf(lpszNoteText, szFmtNoteText, lpszAbstract);
  297. ASSERT(i < NOTE_TEXT_LENGTH);
  298. i = wsprintf(lpszSubject, szFmtSubject, lpszTitle);
  299. ASSERT(i < INTERNET_MAX_URL_LENGTH);
  300. } else {
  301. MLLoadString(IDS_AGNT_MAPIMESSAGE, szFmtNoteText, NOTE_TEXT_LENGTH);
  302. MLLoadString(IDS_AGNT_MAPISUBJECT, szFmtSubject, INTERNET_MAX_URL_LENGTH);
  303. i = wsprintf(lpszNoteText, szFmtNoteText, lpszName, lpszURL);
  304. ASSERT(i < NOTE_TEXT_LENGTH);
  305. i = wsprintf(lpszSubject, szFmtSubject, lpszName);
  306. ASSERT(i < INTERNET_MAX_URL_LENGTH);
  307. }
  308. //
  309. // Build a mapi mail recipient structure
  310. //
  311. lpRecipient->ulRecipClass = MAPI_TO;
  312. lpRecipient->lpszName = lpszEmailAddress;
  313. //
  314. // Fill in the message subject line, recipient and note text
  315. //
  316. lpMessage->nRecipCount = 1;
  317. lpMessage->lpRecips = lpRecipient;
  318. lpMessage->lpszNoteText = lpszNoteText;
  319. lpMessage->lpszSubject = lpszSubject;
  320. }
  321. #endif
  322. //
  323. // Use the MLANG apis to translate the string
  324. //
  325. // Returns success if translation occurred, fails otherwise
  326. //
  327. // Note if lpszSrcCharSet is NULL then use CP_ACP as the codepage
  328. //
  329. HRESULT TranslateCharset(
  330. LPSTR lpszSrcString, LPSTR lpszDstString, UINT uiDstSize,
  331. LPSTR lpszSrcCharset, LPSTR lpszDstCharset
  332. )
  333. {
  334. HRESULT hr = E_FAIL;
  335. WCHAR wszSrcCharset[ENCODING_STRLEN];
  336. WCHAR wszDstCharset[ENCODING_STRLEN];
  337. if (lpszSrcString == NULL || lpszDstString == NULL ||
  338. lpszDstCharset == NULL)
  339. {
  340. return E_INVALIDARG;
  341. }
  342. SHAnsiToUnicode(lpszDstCharset, wszDstCharset, ARRAYSIZE(wszDstCharset));
  343. if (lpszSrcCharset)
  344. SHAnsiToUnicode(lpszSrcCharset, wszSrcCharset, ARRAYSIZE(wszSrcCharset));
  345. LPMULTILANGUAGE2 pIML2 = NULL;
  346. //
  347. // Create the MLANG object
  348. //
  349. if (SUCCEEDED(CoCreateInstance (CLSID_CMultiLanguage, NULL,
  350. CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (void**)&pIML2)))
  351. {
  352. UINT srcCodePage = (UINT)-1, dstCodePage;
  353. MIMECSETINFO mcsi = {0};
  354. //
  355. // First get the source code page either from the passed in string
  356. // name of source Charset or from the default one if null if passed in
  357. //
  358. if (lpszSrcCharset == NULL)
  359. {
  360. srcCodePage = GetACP();
  361. hr = S_OK;
  362. }
  363. else
  364. {
  365. //
  366. // Use the mlang object to get the codepages
  367. //
  368. hr = pIML2->GetCharsetInfo(wszSrcCharset, &mcsi);
  369. if (SUCCEEDED(hr))
  370. {
  371. srcCodePage = mcsi.uiInternetEncoding;
  372. }
  373. }
  374. if (SUCCEEDED(hr))
  375. {
  376. hr = pIML2->GetCharsetInfo(wszDstCharset, &mcsi);
  377. if (SUCCEEDED(hr))
  378. {
  379. dstCodePage = mcsi.uiInternetEncoding;
  380. if (srcCodePage != dstCodePage)
  381. {
  382. //
  383. // To work around a bug in the Mlang::ConvertString api
  384. // have to pass in a ptr to length of the src string
  385. //
  386. UINT uiSrcSize = lstrlenA(lpszSrcString) + 1;
  387. DWORD dwMode = 0;
  388. hr = pIML2->ConvertString(
  389. &dwMode,
  390. srcCodePage,
  391. dstCodePage,
  392. (LPBYTE)lpszSrcString,
  393. &uiSrcSize,
  394. (LPBYTE)lpszDstString,
  395. &uiDstSize);
  396. }
  397. else
  398. {
  399. lstrcpynA(lpszDstString, lpszSrcString, uiDstSize);
  400. }
  401. }
  402. }
  403. pIML2->Release();
  404. }
  405. return hr;
  406. }
  407. //////////////////////////////////////////////////////////////////////////
  408. //
  409. // Mail notification implementation
  410. //
  411. //////////////////////////////////////////////////////////////////////////
  412. //
  413. // Notify via email that the pszURL has changed
  414. //
  415. // There are 3 ways to send via email -
  416. //
  417. // Use straight MAPI (IE Exchange or Outlook)
  418. // Most people don't have Exchange in the real world.
  419. //
  420. // Use Athena's MAPI implementation
  421. // It's broken and doesn't handle UI'less mode
  422. //
  423. // Use straight SMTP,
  424. // Need to get the name of an SMTP server
  425. //
  426. HRESULT
  427. NotifyViaEMail(
  428. LPSTR lpszURL, // url that was downloaded
  429. LPSTR lpszEmailAddress, // email address to send notification to
  430. LPSTR lpszSMTPServer, // SMTP server to use to deliver email
  431. LPSTR &lpszName, // friendly name of url (probably page title)
  432. LPSTR lpszTitle, // optional: NULL if not custom message
  433. LPSTR lpszAbstract, // optional: NULL if not custom message
  434. LPSTR lpszCharSet, // optional: charset of html page
  435. BOOL fSendHTMLEmail ) // TRUE if registry allows it and check mode
  436. // supports it.
  437. {
  438. BOOL b;
  439. LPSTR lpszSMTPMessage;
  440. //
  441. // lpszName comes from the title of the web page. If the charset of the page
  442. // is not the same as the one that this version of IE has been localized to
  443. // then we need to use the MLANG api's to coerce the string into the correct
  444. // charset
  445. //
  446. CHAR szTargetEncoding[ENCODING_STRLEN];
  447. MLLoadStringA(IDS_TARGET_CHARSET_EMAIL, szTargetEncoding, ARRAYSIZE(szTargetEncoding));
  448. //
  449. // Allocate buffer for new name. This is a conversion from one dbcs charset
  450. // to another so size shouldn't but to be safe use *2 multiplier.
  451. //
  452. UINT uiSize = lstrlenA(lpszName) * 2;
  453. LPSTR lpszNewName = (LPSTR) MemAlloc(LMEM_FIXED, uiSize * sizeof(CHAR));
  454. if (lpszNewName)
  455. {
  456. //
  457. // Note check for S_OK as will return S_FALSE if there is no appropriate
  458. // translation installed on this machine
  459. //
  460. if (S_OK == TranslateCharset(lpszName, lpszNewName, uiSize, lpszCharSet,
  461. szTargetEncoding))
  462. {
  463. //
  464. // if translation occurred alias new name to old name
  465. //
  466. SAFELOCALFREE(lpszName);
  467. lpszName = lpszNewName;
  468. }
  469. else
  470. {
  471. SAFELOCALFREE(lpszNewName); // don't need newname after all
  472. }
  473. }
  474. //
  475. // If we are requested to HTML mail and we successfully built the html
  476. //
  477. if (!(fSendHTMLEmail &&
  478. BuildHTMLMessage(lpszEmailAddress, lpszName, lpszURL, &lpszSMTPMessage,
  479. lpszTitle, lpszAbstract, lpszCharSet)))
  480. {
  481. //
  482. // If sending a simple notification or BuildHTMLMessage failed
  483. // force fSendHTMLEmail to false and build simple smtp message
  484. //
  485. fSendHTMLEmail = FALSE;
  486. BuildSMTPMessage(lpszName, lpszURL, &lpszSMTPMessage, lpszTitle, lpszAbstract);
  487. }
  488. //
  489. // Disable MAPI for now
  490. //
  491. //-----------------------------------------
  492. //BUG BUG: If this is enabled then wsprintf on message text should be changed to FormatMessage
  493. // due to 1KB message limit.
  494. #if 0
  495. //
  496. // First try and load a full mapi implementation (exchange or outlook)
  497. //
  498. HMODULE hmodMail = LoadNormalMapi();
  499. if (hmodMail != NULL)
  500. {
  501. //
  502. // Get mapi function entry points
  503. //
  504. LPMAPISENDMAIL pfnSendMail;
  505. LPMAPILOGON pfnLogon;
  506. MapiMessage message;
  507. MapiRecipDesc recipient;
  508. pfnSendMail = (LPMAPISENDMAIL)GetProcAddress(hmodMail, "MAPISendMail");
  509. pfnLogon = (LPMAPILOGON) GetProcAddress(hmodMail, "MAPILogon");
  510. if (pfnSendMail != NULL && pfnLogon != NULL)
  511. {
  512. //
  513. // Logon to mapi provider
  514. //
  515. LHANDLE hSession = 0;
  516. LPSTR lpszProfileName = NULL; // for now logon on with NULL
  517. LPSTR lpszPassword = NULL; // credentials
  518. ULONG ul = pfnLogon(0, lpszProfileName, lpszPassword, 0, 0, &hSession);
  519. if (ul != SUCCESS_SUCCESS)
  520. {
  521. DBG_OUTPUT_MAPI_ERROR(ul);
  522. //
  523. // Fall through to try other mail delivery methods
  524. //
  525. }
  526. else
  527. {
  528. TCHAR szSubject[INTERNET_MAX_URL_LENGTH];
  529. //
  530. // Fill in the text, subject line and recipient in mapi message
  531. //
  532. BuildMAPIMessage(lpszName, lpszURL, lpszEmailAddress,
  533. &message, &recipient,
  534. szSubject, lpszSMTPMessage, szTitle, szAbstract);
  535. //
  536. // Actually send the message via MAPI with no UI
  537. //
  538. ul = pfnSendMail(0, 0, &message, 0, 0);
  539. if (ul != SUCCESS_SUCCESS)
  540. {
  541. DBG_OUTPUT_MAPI_ERROR(ul);
  542. }
  543. else
  544. {
  545. FreeLibrary(hmodMail);
  546. return S_OK;
  547. }
  548. }
  549. }
  550. FreeLibrary(hmodMail);
  551. }
  552. #endif
  553. //
  554. // Send message to given address and from given address
  555. //
  556. if (lpszSMTPMessage)
  557. {
  558. b = SMTPSendMessage(lpszSMTPServer, lpszEmailAddress,
  559. lpszEmailAddress, lpszSMTPMessage);
  560. MemFree(lpszSMTPMessage);
  561. }
  562. else
  563. {
  564. b = FALSE;
  565. }
  566. if (b)
  567. return S_OK;
  568. return E_FAIL;
  569. }
  570. //////////////////////////////////////////////////////////////////////////
  571. //
  572. // Helper function to send email
  573. //
  574. //////////////////////////////////////////////////////////////////////////
  575. HRESULT SendEmailFromItem(ISubscriptionItem *pItem)
  576. {
  577. HRESULT hr = E_FAIL;
  578. LPSTR pszURL = NULL;
  579. LPSTR pszName = NULL;
  580. LPSTR pszTitle = NULL;
  581. LPSTR pszAbstract = NULL;
  582. LPSTR pszCharSet = NULL;
  583. // Get the Email URL to send. Fall back to the download URL.
  584. ReadAnsiSTR(pItem, c_szPropEmailURL, &pszURL);
  585. if (!pszURL)
  586. ReadAnsiSTR(pItem, c_szPropURL, &pszURL);
  587. ASSERT(pszURL);
  588. // Get the friendly name. Fall back to the download URL.
  589. ReadAnsiSTR(pItem, c_szPropName, &pszName);
  590. ASSERT(pszName);
  591. if (!pszName)
  592. ReadAnsiSTR(pItem, c_szPropURL, &pszName);
  593. // Get Email Title and Abstract if flag is set.
  594. DWORD dwEmailFlags = 0;
  595. ReadDWORD(pItem, c_szPropEmailFlags, &dwEmailFlags);
  596. if (dwEmailFlags & MAILAGENT_FLAG_CUSTOM_MSG)
  597. {
  598. ReadAnsiSTR(pItem, c_szPropEmailTitle, &pszTitle);
  599. ASSERT(pszTitle);
  600. ReadAnsiSTR(pItem, c_szPropEmailAbstract, &pszAbstract);
  601. ASSERT(pszAbstract);
  602. }
  603. //
  604. // Get the charset in the notification
  605. //
  606. ReadAnsiSTR(pItem, c_szPropCharSet, &pszCharSet);
  607. // Get Email address and SMTP server
  608. TCHAR tszBuf[MAX_PATH];
  609. CHAR szEmailAddress[MAX_PATH];
  610. CHAR szSMTPServer[MAX_PATH];
  611. ReadDefaultEmail(tszBuf, ARRAYSIZE(tszBuf));
  612. SHTCharToAnsi(tszBuf, szEmailAddress, ARRAYSIZE(szEmailAddress));
  613. ReadDefaultSMTPServer(tszBuf, ARRAYSIZE(tszBuf));
  614. SHTCharToAnsi(tszBuf, szSMTPServer, ARRAYSIZE(szSMTPServer));
  615. // Send the email
  616. if (pszURL && pszName)
  617. {
  618. //
  619. // Check if HTML Mail notification is enabled or disabled thru the registry
  620. //
  621. BOOL fSendHTMLEmail = FALSE;
  622. if (!ReadRegValue(HKEY_CURRENT_USER, c_szRegKey,
  623. TEXT("EnableHTMLMailNotification"),
  624. &fSendHTMLEmail, sizeof(DWORD)))
  625. {
  626. fSendHTMLEmail = TRUE; // default to on if not read from registry
  627. }
  628. // Now make sure our crawling mode supports HTML mail. We don't
  629. // want to send HTML if we're in check-for-change only.
  630. DWORD dwTemp = 0;
  631. ReadDWORD(pItem, c_szPropCrawlChangesOnly, &dwTemp);
  632. if (dwTemp != 0)
  633. {
  634. fSendHTMLEmail = FALSE;
  635. }
  636. // else, leave fSendHTMLEmail in its reg-based setting.
  637. hr = NotifyViaEMail(pszURL, szEmailAddress, szSMTPServer,
  638. pszName, pszTitle, pszAbstract, pszCharSet,
  639. fSendHTMLEmail );
  640. }
  641. // Clean up.
  642. SAFELOCALFREE(pszURL);
  643. SAFELOCALFREE(pszName);
  644. SAFELOCALFREE(pszTitle);
  645. SAFELOCALFREE(pszAbstract);
  646. return hr;
  647. }