Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensmtptransport.c
Go to the documentation of this file.
00001 /* 00002 * SMTP Transport 00003 * 00004 * Copyright 2006 Robert Shearman for CodeWeavers 00005 * Copyright 2008 Hans Leidekker for CodeWeavers 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 * 00021 */ 00022 00023 #define COBJMACROS 00024 00025 #include <stdarg.h> 00026 #include <stdio.h> 00027 00028 #include "windef.h" 00029 #include "winbase.h" 00030 #include "winnt.h" 00031 #include "winuser.h" 00032 #include "objbase.h" 00033 #include "mimeole.h" 00034 #include "wine/debug.h" 00035 00036 #include "inetcomm_private.h" 00037 00038 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm); 00039 00040 typedef struct 00041 { 00042 InternetTransport InetTransport; 00043 ULONG refs; 00044 BOOL fESMTP; 00045 SMTPMESSAGE pending_message; 00046 INETADDR *addrlist; 00047 ULONG ulCurrentAddressIndex; 00048 } SMTPTransport; 00049 00050 static HRESULT SMTPTransport_ParseResponse(SMTPTransport *This, char *pszResponse, SMTPRESPONSE *pResponse) 00051 { 00052 HRESULT hrServerError; 00053 00054 TRACE("response: %s\n", debugstr_a(pszResponse)); 00055 00056 if (!isdigit(*pszResponse)) 00057 return IXP_E_SMTP_RESPONSE_ERROR; 00058 pResponse->pTransport = (ISMTPTransport *)&This->InetTransport.u.vtblSMTP2; 00059 pResponse->rIxpResult.pszResponse = pszResponse; 00060 pResponse->rIxpResult.dwSocketError = 0; 00061 pResponse->rIxpResult.uiServerError = strtol(pszResponse, &pszResponse, 10); 00062 if (*pszResponse == '-') 00063 { 00064 pResponse->fDone = FALSE; 00065 pszResponse++; 00066 } 00067 else 00068 pResponse->fDone = TRUE; 00069 00070 switch (pResponse->rIxpResult.uiServerError) 00071 { 00072 case 211: hrServerError = IXP_E_SMTP_211_SYSTEM_STATUS; break; 00073 case 214: hrServerError = IXP_E_SMTP_214_HELP_MESSAGE; break; 00074 case 220: hrServerError = IXP_E_SMTP_220_READY; break; 00075 case 221: hrServerError = IXP_E_SMTP_221_CLOSING; break; 00076 case 245: hrServerError = IXP_E_SMTP_245_AUTH_SUCCESS; break; 00077 case 250: hrServerError = IXP_E_SMTP_250_MAIL_ACTION_OKAY; break; 00078 case 251: hrServerError = IXP_E_SMTP_251_FORWARDING_MAIL; break; 00079 case 334: hrServerError = IXP_E_SMTP_334_AUTH_READY_RESPONSE; break; 00080 case 354: hrServerError = IXP_E_SMTP_354_START_MAIL_INPUT; break; 00081 case 421: hrServerError = IXP_E_SMTP_421_NOT_AVAILABLE; break; 00082 case 450: hrServerError = IXP_E_SMTP_450_MAILBOX_BUSY; break; 00083 case 451: hrServerError = IXP_E_SMTP_451_ERROR_PROCESSING; break; 00084 case 452: hrServerError = IXP_E_SMTP_452_NO_SYSTEM_STORAGE; break; 00085 case 454: hrServerError = IXP_E_SMTP_454_STARTTLS_FAILED; break; 00086 case 500: hrServerError = IXP_E_SMTP_500_SYNTAX_ERROR; break; 00087 case 501: hrServerError = IXP_E_SMTP_501_PARAM_SYNTAX; break; 00088 case 502: hrServerError = IXP_E_SMTP_502_COMMAND_NOTIMPL; break; 00089 case 503: hrServerError = IXP_E_SMTP_503_COMMAND_SEQ; break; 00090 case 504: hrServerError = IXP_E_SMTP_504_COMMAND_PARAM_NOTIMPL; break; 00091 case 530: hrServerError = IXP_E_SMTP_530_STARTTLS_REQUIRED; break; 00092 case 550: hrServerError = IXP_E_SMTP_550_MAILBOX_NOT_FOUND; break; 00093 case 551: hrServerError = IXP_E_SMTP_551_USER_NOT_LOCAL; break; 00094 case 552: hrServerError = IXP_E_SMTP_552_STORAGE_OVERFLOW; break; 00095 case 553: hrServerError = IXP_E_SMTP_553_MAILBOX_NAME_SYNTAX; break; 00096 case 554: hrServerError = IXP_E_SMTP_554_TRANSACT_FAILED; break; 00097 default: 00098 hrServerError = IXP_E_SMTP_RESPONSE_ERROR; 00099 break; 00100 } 00101 pResponse->rIxpResult.hrResult = hrServerError; 00102 pResponse->rIxpResult.hrServerError = hrServerError; 00103 00104 if (This->InetTransport.pCallback && This->InetTransport.fCommandLogging) 00105 { 00106 ITransportCallback_OnCommand(This->InetTransport.pCallback, CMD_RESP, 00107 pResponse->rIxpResult.pszResponse, hrServerError, 00108 (IInternetTransport *)&This->InetTransport.u.vtbl); 00109 } 00110 return S_OK; 00111 } 00112 00113 static void SMTPTransport_CallbackDoNothing(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00114 { 00115 TRACE("\n"); 00116 } 00117 00118 static void SMTPTransport_CallbackReadResponseDoNothing(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00119 { 00120 SMTPTransport *This = (SMTPTransport *)iface; 00121 00122 TRACE("\n"); 00123 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackDoNothing); 00124 } 00125 00126 static void SMTPTransport_CallbackProcessDATAResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00127 { 00128 SMTPTransport *This = (SMTPTransport *)iface; 00129 SMTPRESPONSE response = { 0 }; 00130 HRESULT hr; 00131 00132 TRACE("\n"); 00133 00134 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00135 if (FAILED(hr)) 00136 { 00137 /* FIXME: handle error */ 00138 return; 00139 } 00140 00141 response.command = SMTP_DATA; 00142 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response); 00143 00144 if (FAILED(response.rIxpResult.hrServerError)) 00145 { 00146 ERR("server error: %s\n", debugstr_a(pBuffer)); 00147 /* FIXME: handle error */ 00148 return; 00149 } 00150 } 00151 00152 static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00153 { 00154 SMTPTransport *This = (SMTPTransport *)iface; 00155 00156 TRACE("\n"); 00157 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackProcessDATAResponse); 00158 } 00159 00160 static void SMTPTransport_CallbackProcessMAILResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00161 { 00162 SMTPTransport *This = (SMTPTransport *)iface; 00163 SMTPRESPONSE response = { 0 }; 00164 HRESULT hr; 00165 00166 TRACE("\n"); 00167 00168 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00169 if (FAILED(hr)) 00170 { 00171 /* FIXME: handle error */ 00172 return; 00173 } 00174 00175 response.command = SMTP_MAIL; 00176 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response); 00177 00178 if (FAILED(response.rIxpResult.hrServerError)) 00179 { 00180 ERR("server error: %s\n", debugstr_a(pBuffer)); 00181 /* FIXME: handle error */ 00182 return; 00183 } 00184 } 00185 00186 static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00187 { 00188 SMTPTransport *This = (SMTPTransport *)iface; 00189 00190 TRACE("\n"); 00191 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackProcessMAILResponse); 00192 } 00193 00194 static void SMTPTransport_CallbackProcessRCPTResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00195 { 00196 SMTPTransport *This = (SMTPTransport *)iface; 00197 SMTPRESPONSE response = { 0 }; 00198 HRESULT hr; 00199 00200 TRACE("\n"); 00201 00202 HeapFree(GetProcessHeap(), 0, This->addrlist); 00203 This->addrlist = NULL; 00204 00205 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00206 if (FAILED(hr)) 00207 { 00208 /* FIXME: handle error */ 00209 return; 00210 } 00211 00212 response.command = SMTP_RCPT; 00213 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response); 00214 00215 if (FAILED(response.rIxpResult.hrServerError)) 00216 { 00217 ERR("server error: %s\n", debugstr_a(pBuffer)); 00218 /* FIXME: handle error */ 00219 return; 00220 } 00221 } 00222 00223 static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00224 { 00225 SMTPTransport *This = (SMTPTransport *)iface; 00226 00227 TRACE("\n"); 00228 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackProcessRCPTResponse); 00229 } 00230 00231 static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00232 { 00233 SMTPTransport *This = (SMTPTransport *)iface; 00234 SMTPRESPONSE response = { 0 }; 00235 HRESULT hr; 00236 00237 TRACE("\n"); 00238 00239 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00240 if (FAILED(hr)) 00241 { 00242 /* FIXME: handle error */ 00243 return; 00244 } 00245 00246 response.command = This->fESMTP ? SMTP_EHLO : SMTP_HELO; 00247 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response); 00248 00249 if (FAILED(response.rIxpResult.hrServerError)) 00250 { 00251 ERR("server error: %s\n", debugstr_a(pBuffer)); 00252 /* FIXME: handle error */ 00253 return; 00254 } 00255 00256 if (!response.fDone) 00257 { 00258 InternetTransport_ReadLine(&This->InetTransport, 00259 SMTPTransport_CallbackProcessHelloResp); 00260 return; 00261 } 00262 00263 /* FIXME: try to authorize */ 00264 00265 /* always changed to this status, even if authorization not support on server */ 00266 InternetTransport_ChangeStatus(&This->InetTransport, IXP_AUTHORIZED); 00267 InternetTransport_ChangeStatus(&This->InetTransport, IXP_CONNECTED); 00268 00269 memset(&response, 0, sizeof(response)); 00270 response.command = SMTP_CONNECTED; 00271 response.fDone = TRUE; 00272 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response); 00273 } 00274 00275 static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00276 { 00277 SMTPTransport *This = (SMTPTransport *)iface; 00278 00279 TRACE("\n"); 00280 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackProcessHelloResp); 00281 } 00282 00283 static void SMTPTransport_CallbackSendHello(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00284 { 00285 SMTPTransport *This = (SMTPTransport *)iface; 00286 SMTPRESPONSE response = { 0 }; 00287 HRESULT hr; 00288 const char *pszHello; 00289 char *pszCommand; 00290 const char szHostName[] = "localhost"; /* FIXME */ 00291 00292 TRACE("\n"); 00293 00294 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00295 if (FAILED(hr)) 00296 { 00297 /* FIXME: handle error */ 00298 return; 00299 } 00300 00301 response.command = SMTP_BANNER; 00302 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response); 00303 00304 if (FAILED(response.rIxpResult.hrServerError)) 00305 { 00306 ERR("server error: %s\n", debugstr_a(pBuffer)); 00307 /* FIXME: handle error */ 00308 return; 00309 } 00310 00311 TRACE("(%s)\n", pBuffer); 00312 00313 This->fESMTP = strstr(response.rIxpResult.pszResponse, "ESMTP") && 00314 This->InetTransport.ServerInfo.dwFlags & (ISF_SSLONSAMEPORT|ISF_QUERYDSNSUPPORT|ISF_QUERYAUTHSUPPORT); 00315 00316 if (This->fESMTP) 00317 pszHello = "EHLO "; 00318 else 00319 pszHello = "HELO "; 00320 00321 pszCommand = HeapAlloc(GetProcessHeap(), 0, strlen(pszHello) + strlen(szHostName) + 2); 00322 strcpy(pszCommand, pszHello); 00323 strcat(pszCommand, szHostName); 00324 pszCommand[strlen(pszCommand)+1] = '\0'; 00325 pszCommand[strlen(pszCommand)] = '\n'; 00326 00327 InternetTransport_DoCommand(&This->InetTransport, pszCommand, 00328 SMTPTransport_CallbackRecvHelloResp); 00329 00330 HeapFree(GetProcessHeap(), 0, pszCommand); 00331 } 00332 00333 static void SMTPTransport_CallbackDisconnect(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00334 { 00335 SMTPTransport *This = (SMTPTransport *)iface; 00336 SMTPRESPONSE response; 00337 HRESULT hr; 00338 00339 TRACE("\n"); 00340 00341 if (pBuffer) 00342 { 00343 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00344 if (FAILED(hr)) 00345 { 00346 /* FIXME: handle error */ 00347 return; 00348 } 00349 00350 if (FAILED(response.rIxpResult.hrServerError)) 00351 { 00352 ERR("server error: %s\n", debugstr_a(pBuffer)); 00353 /* FIXME: handle error */ 00354 return; 00355 } 00356 } 00357 InternetTransport_DropConnection(&This->InetTransport); 00358 } 00359 00360 static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00361 { 00362 SMTPTransport *This = (SMTPTransport *)iface; 00363 SMTPRESPONSE response = { 0 }; 00364 HRESULT hr; 00365 00366 TRACE("\n"); 00367 00368 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00369 if (FAILED(hr)) 00370 { 00371 /* FIXME: handle error */ 00372 return; 00373 } 00374 00375 if (FAILED(response.rIxpResult.hrServerError)) 00376 { 00377 ERR("server error: %s\n", debugstr_a(pBuffer)); 00378 /* FIXME: handle error */ 00379 return; 00380 } 00381 00382 response.command = SMTP_SEND_MESSAGE; 00383 response.rIxpResult.hrResult = S_OK; 00384 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response); 00385 } 00386 00387 static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00388 { 00389 SMTPTransport *This = (SMTPTransport *)iface; 00390 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackMessageProcessResponse); 00391 } 00392 00393 static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00394 { 00395 SMTPTransport *This = (SMTPTransport *)iface; 00396 00397 IStream_Release(This->pending_message.pstmMsg); 00398 InternetTransport_DoCommand(&This->InetTransport, "\n.\n", 00399 SMTPTransport_CallbackMessageReadResponse); 00400 } 00401 00402 static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00403 { 00404 SMTPTransport *This = (SMTPTransport *)iface; 00405 SMTPRESPONSE response; 00406 HRESULT hr; 00407 char *pszBuffer; 00408 ULONG cbSize; 00409 00410 TRACE("\n"); 00411 00412 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00413 if (FAILED(hr)) 00414 { 00415 /* FIXME: handle error */ 00416 return; 00417 } 00418 00419 if (FAILED(response.rIxpResult.hrServerError)) 00420 { 00421 ERR("server error: %s\n", debugstr_a(pBuffer)); 00422 /* FIXME: handle error */ 00423 return; 00424 } 00425 00426 pszBuffer = HeapAlloc(GetProcessHeap(), 0, This->pending_message.cbSize); 00427 hr = IStream_Read(This->pending_message.pstmMsg, pszBuffer, This->pending_message.cbSize, NULL); 00428 if (FAILED(hr)) 00429 { 00430 /* FIXME: handle error */ 00431 return; 00432 } 00433 cbSize = This->pending_message.cbSize; 00434 00435 /* FIXME: map "\n.\n" to "\n..\n", reallocate memory, update cbSize */ 00436 00437 /* FIXME: properly stream the message rather than writing it all at once */ 00438 00439 hr = InternetTransport_Write(&This->InetTransport, pszBuffer, cbSize, 00440 SMTPTransport_CallbackMessageSendDOT); 00441 00442 HeapFree(GetProcessHeap(), 0, pszBuffer); 00443 } 00444 00445 static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00446 { 00447 SMTPTransport *This = (SMTPTransport *)iface; 00448 00449 TRACE("\n"); 00450 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackMessageSendDataStream); 00451 } 00452 00453 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer); 00454 00455 static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00456 { 00457 SMTPTransport *This = (SMTPTransport *)iface; 00458 00459 TRACE("\n"); 00460 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackMessageSendTo); 00461 } 00462 00463 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00464 { 00465 SMTPTransport *This = (SMTPTransport *)iface; 00466 SMTPRESPONSE response; 00467 HRESULT hr; 00468 00469 TRACE("\n"); 00470 00471 hr = SMTPTransport_ParseResponse(This, pBuffer, &response); 00472 if (FAILED(hr)) 00473 { 00474 /* FIXME: handle error */ 00475 return; 00476 } 00477 00478 if (FAILED(response.rIxpResult.hrServerError)) 00479 { 00480 ERR("server error: %s\n", debugstr_a(pBuffer)); 00481 /* FIXME: handle error */ 00482 return; 00483 } 00484 00485 for (; This->ulCurrentAddressIndex < This->pending_message.rAddressList.cAddress; This->ulCurrentAddressIndex++) 00486 { 00487 TRACE("address[%d]: %s\n", This->ulCurrentAddressIndex, 00488 This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail); 00489 00490 if ((This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].addrtype & ADDR_TOFROM_MASK) == ADDR_TO) 00491 { 00492 const char szCommandFormat[] = "RCPT TO: <%s>\n"; 00493 char *szCommand; 00494 int len = sizeof(szCommandFormat) - 2 /* "%s" */ + 00495 strlen(This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail); 00496 00497 szCommand = HeapAlloc(GetProcessHeap(), 0, len); 00498 if (!szCommand) 00499 return; 00500 00501 sprintf(szCommand, szCommandFormat, 00502 This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail); 00503 00504 This->ulCurrentAddressIndex++; 00505 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand, 00506 SMTPTransport_CallbackMessageReadToResponse); 00507 00508 HeapFree(GetProcessHeap(), 0, szCommand); 00509 return; 00510 } 00511 } 00512 00513 hr = InternetTransport_DoCommand(&This->InetTransport, "DATA\n", 00514 SMTPTransport_CallbackMessageReadDataResponse); 00515 } 00516 00517 static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer) 00518 { 00519 SMTPTransport *This = (SMTPTransport *)iface; 00520 00521 TRACE("\n"); 00522 InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackMessageSendTo); 00523 } 00524 00525 static HRESULT WINAPI SMTPTransport_QueryInterface(ISMTPTransport2 *iface, REFIID riid, void **ppv) 00526 { 00527 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); 00528 00529 if (IsEqualIID(riid, &IID_IUnknown) || 00530 IsEqualIID(riid, &IID_IInternetTransport) || 00531 IsEqualIID(riid, &IID_ISMTPTransport) || 00532 IsEqualIID(riid, &IID_ISMTPTransport2)) 00533 { 00534 *ppv = iface; 00535 IUnknown_AddRef(iface); 00536 return S_OK; 00537 } 00538 *ppv = NULL; 00539 FIXME("no interface for %s\n", debugstr_guid(riid)); 00540 return E_NOINTERFACE; 00541 } 00542 00543 static ULONG WINAPI SMTPTransport_AddRef(ISMTPTransport2 *iface) 00544 { 00545 SMTPTransport *This = (SMTPTransport *)iface; 00546 return InterlockedIncrement((LONG *)&This->refs); 00547 } 00548 00549 static ULONG WINAPI SMTPTransport_Release(ISMTPTransport2 *iface) 00550 { 00551 SMTPTransport *This = (SMTPTransport *)iface; 00552 ULONG refs = InterlockedDecrement((LONG *)&This->refs); 00553 if (!refs) 00554 { 00555 TRACE("destroying %p\n", This); 00556 if (This->InetTransport.Status != IXP_DISCONNECTED) 00557 InternetTransport_DropConnection(&This->InetTransport); 00558 00559 if (This->InetTransport.pCallback) ITransportCallback_Release(This->InetTransport.pCallback); 00560 HeapFree(GetProcessHeap(), 0, This->addrlist); 00561 HeapFree(GetProcessHeap(), 0, This); 00562 } 00563 return refs; 00564 } 00565 00566 static HRESULT WINAPI SMTPTransport_GetServerInfo(ISMTPTransport2 *iface, 00567 LPINETSERVER pInetServer) 00568 { 00569 SMTPTransport *This = (SMTPTransport *)iface; 00570 00571 TRACE("(%p)\n", pInetServer); 00572 return InternetTransport_GetServerInfo(&This->InetTransport, pInetServer); 00573 } 00574 00575 static IXPTYPE WINAPI SMTPTransport_GetIXPType(ISMTPTransport2 *iface) 00576 { 00577 TRACE("()\n"); 00578 return IXP_SMTP; 00579 } 00580 00581 static HRESULT WINAPI SMTPTransport_IsState(ISMTPTransport2 *iface, 00582 IXPISSTATE isstate) 00583 { 00584 FIXME("(%d): stub\n", isstate); 00585 return E_NOTIMPL; 00586 } 00587 00588 static HRESULT WINAPI SMTPTransport_InetServerFromAccount( 00589 ISMTPTransport2 *iface, IImnAccount *pAccount, LPINETSERVER pInetServer) 00590 { 00591 SMTPTransport *This = (SMTPTransport *)iface; 00592 00593 TRACE("(%p, %p)\n", pAccount, pInetServer); 00594 return InternetTransport_InetServerFromAccount(&This->InetTransport, pAccount, pInetServer); 00595 } 00596 00597 static HRESULT WINAPI SMTPTransport_Connect(ISMTPTransport2 *iface, 00598 LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging) 00599 { 00600 SMTPTransport *This = (SMTPTransport *)iface; 00601 HRESULT hr; 00602 00603 TRACE("(%p, %s, %s)\n", pInetServer, fAuthenticate ? "TRUE" : "FALSE", fCommandLogging ? "TRUE" : "FALSE"); 00604 00605 hr = InternetTransport_Connect(&This->InetTransport, pInetServer, fAuthenticate, fCommandLogging); 00606 if (FAILED(hr)) 00607 return hr; 00608 00609 /* this starts the state machine, which continues in SMTPTransport_CallbackSendHELO */ 00610 return InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackSendHello); 00611 } 00612 00613 static HRESULT WINAPI SMTPTransport_HandsOffCallback(ISMTPTransport2 *iface) 00614 { 00615 SMTPTransport *This = (SMTPTransport *)iface; 00616 00617 TRACE("()\n"); 00618 return InternetTransport_HandsOffCallback(&This->InetTransport); 00619 } 00620 00621 static HRESULT WINAPI SMTPTransport_Disconnect(ISMTPTransport2 *iface) 00622 { 00623 TRACE("()\n"); 00624 return ISMTPTransport2_CommandQUIT(iface); 00625 } 00626 00627 static HRESULT WINAPI SMTPTransport_DropConnection(ISMTPTransport2 *iface) 00628 { 00629 SMTPTransport *This = (SMTPTransport *)iface; 00630 00631 TRACE("()\n"); 00632 return InternetTransport_DropConnection(&This->InetTransport); 00633 } 00634 00635 static HRESULT WINAPI SMTPTransport_GetStatus(ISMTPTransport2 *iface, 00636 IXPSTATUS *pCurrentStatus) 00637 { 00638 SMTPTransport *This = (SMTPTransport *)iface; 00639 00640 TRACE("()\n"); 00641 return InternetTransport_GetStatus(&This->InetTransport, pCurrentStatus); 00642 } 00643 00644 static HRESULT WINAPI SMTPTransport_InitNew(ISMTPTransport2 *iface, 00645 LPSTR pszLogFilePath, ISMTPCallback *pCallback) 00646 { 00647 SMTPTransport *This = (SMTPTransport *)iface; 00648 00649 TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath), pCallback); 00650 00651 if (!pCallback) 00652 return E_INVALIDARG; 00653 00654 if (pszLogFilePath) 00655 FIXME("not using log file of %s, use Wine debug logging instead\n", 00656 debugstr_a(pszLogFilePath)); 00657 00658 ISMTPCallback_AddRef(pCallback); 00659 This->InetTransport.pCallback = (ITransportCallback *)pCallback; 00660 This->InetTransport.fInitialised = TRUE; 00661 00662 return S_OK; 00663 } 00664 00665 static HRESULT WINAPI SMTPTransport_SendMessage(ISMTPTransport2 *iface, 00666 LPSMTPMESSAGE pMessage) 00667 { 00668 SMTPTransport *This = (SMTPTransport *)iface; 00669 ULONG i, size; 00670 LPSTR pszFromAddress = NULL; 00671 const char szCommandFormat[] = "MAIL FROM: <%s>\n"; 00672 char *szCommand; 00673 int len; 00674 HRESULT hr; 00675 00676 TRACE("(%p)\n", pMessage); 00677 00678 This->pending_message = *pMessage; 00679 IStream_AddRef(pMessage->pstmMsg); 00680 00681 size = pMessage->rAddressList.cAddress * sizeof(INETADDR); 00682 This->addrlist = HeapAlloc(GetProcessHeap(), 0, size); 00683 if (!This->addrlist) 00684 return E_OUTOFMEMORY; 00685 00686 memcpy(This->addrlist, pMessage->rAddressList.prgAddress, size); 00687 This->pending_message.rAddressList.prgAddress = This->addrlist; 00688 This->ulCurrentAddressIndex = 0; 00689 00690 for (i = 0; i < pMessage->rAddressList.cAddress; i++) 00691 { 00692 if ((pMessage->rAddressList.prgAddress[i].addrtype & ADDR_TOFROM_MASK) == ADDR_FROM) 00693 { 00694 TRACE("address[%d]: ADDR_FROM, %s\n", i, 00695 pMessage->rAddressList.prgAddress[i].szEmail); 00696 pszFromAddress = pMessage->rAddressList.prgAddress[i].szEmail; 00697 } 00698 else if ((pMessage->rAddressList.prgAddress[i].addrtype & ADDR_TOFROM_MASK) == ADDR_TO) 00699 { 00700 TRACE("address[%d]: ADDR_TO, %s\n", i, 00701 pMessage->rAddressList.prgAddress[i].szEmail); 00702 } 00703 } 00704 00705 if (!pszFromAddress) 00706 { 00707 SMTPRESPONSE response; 00708 memset(&response, 0, sizeof(response)); 00709 response.command = SMTP_SEND_MESSAGE; 00710 response.fDone = TRUE; 00711 response.pTransport = (ISMTPTransport *)&This->InetTransport.u.vtblSMTP2; 00712 response.rIxpResult.hrResult = IXP_E_SMTP_NO_SENDER; 00713 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response); 00714 return S_OK; 00715 } 00716 len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszFromAddress); 00717 00718 szCommand = HeapAlloc(GetProcessHeap(), 0, len); 00719 if (!szCommand) 00720 return E_OUTOFMEMORY; 00721 00722 sprintf(szCommand, szCommandFormat, pszFromAddress); 00723 00724 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand, 00725 SMTPTransport_CallbackMessageReadFromResponse); 00726 00727 return hr; 00728 } 00729 00730 static HRESULT WINAPI SMTPTransport_CommandMAIL(ISMTPTransport2 *iface, LPSTR pszEmailFrom) 00731 { 00732 SMTPTransport *This = (SMTPTransport *)iface; 00733 const char szCommandFormat[] = "MAIL FROM: <%s>\n"; 00734 char *szCommand; 00735 int len; 00736 HRESULT hr; 00737 00738 TRACE("(%s)\n", debugstr_a(pszEmailFrom)); 00739 00740 if (!pszEmailFrom) 00741 return E_INVALIDARG; 00742 00743 len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailFrom); 00744 szCommand = HeapAlloc(GetProcessHeap(), 0, len); 00745 if (!szCommand) 00746 return E_OUTOFMEMORY; 00747 00748 sprintf(szCommand, szCommandFormat, pszEmailFrom); 00749 00750 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand, 00751 SMTPTransport_CallbackReadMAILResponse); 00752 00753 HeapFree(GetProcessHeap(), 0, szCommand); 00754 return hr; 00755 } 00756 00757 static HRESULT WINAPI SMTPTransport_CommandRCPT(ISMTPTransport2 *iface, LPSTR pszEmailTo) 00758 { 00759 SMTPTransport *This = (SMTPTransport *)iface; 00760 const char szCommandFormat[] = "RCPT TO: <%s>\n"; 00761 char *szCommand; 00762 int len; 00763 HRESULT hr; 00764 00765 TRACE("(%s)\n", debugstr_a(pszEmailTo)); 00766 00767 if (!pszEmailTo) 00768 return E_INVALIDARG; 00769 00770 len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailTo); 00771 szCommand = HeapAlloc(GetProcessHeap(), 0, len); 00772 if (!szCommand) 00773 return E_OUTOFMEMORY; 00774 00775 sprintf(szCommand, szCommandFormat, pszEmailTo); 00776 00777 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand, 00778 SMTPTransport_CallbackReadRCPTResponse); 00779 00780 HeapFree(GetProcessHeap(), 0, szCommand); 00781 return hr; 00782 } 00783 00784 static HRESULT WINAPI SMTPTransport_CommandEHLO(ISMTPTransport2 *iface) 00785 { 00786 SMTPTransport *This = (SMTPTransport *)iface; 00787 const char szCommandFormat[] = "EHLO %s\n"; 00788 const char szHostname[] = "localhost"; /* FIXME */ 00789 char *szCommand; 00790 int len = sizeof(szCommandFormat) - 2 /* "%s" */ + sizeof(szHostname); 00791 HRESULT hr; 00792 00793 TRACE("\n"); 00794 00795 szCommand = HeapAlloc(GetProcessHeap(), 0, len); 00796 if (!szCommand) 00797 return E_OUTOFMEMORY; 00798 00799 sprintf(szCommand, szCommandFormat, szHostname); 00800 00801 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand, 00802 SMTPTransport_CallbackReadResponseDoNothing); 00803 00804 HeapFree(GetProcessHeap(), 0, szCommand); 00805 return hr; 00806 } 00807 00808 static HRESULT WINAPI SMTPTransport_CommandHELO(ISMTPTransport2 *iface) 00809 { 00810 SMTPTransport *This = (SMTPTransport *)iface; 00811 const char szCommandFormat[] = "HELO %s\n"; 00812 const char szHostname[] = "localhost"; /* FIXME */ 00813 char *szCommand; 00814 int len = sizeof(szCommandFormat) - 2 /* "%s" */ + sizeof(szHostname); 00815 HRESULT hr; 00816 00817 TRACE("()\n"); 00818 00819 szCommand = HeapAlloc(GetProcessHeap(), 0, len); 00820 if (!szCommand) 00821 return E_OUTOFMEMORY; 00822 00823 sprintf(szCommand, szCommandFormat, szHostname); 00824 00825 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand, 00826 SMTPTransport_CallbackReadResponseDoNothing); 00827 00828 HeapFree(GetProcessHeap(), 0, szCommand); 00829 return hr; 00830 } 00831 00832 static HRESULT WINAPI SMTPTransport_CommandAUTH(ISMTPTransport2 *iface, 00833 LPSTR pszAuthType) 00834 { 00835 SMTPTransport *This = (SMTPTransport *)iface; 00836 const char szCommandFormat[] = "AUTH %s\n"; 00837 char *szCommand; 00838 int len; 00839 HRESULT hr; 00840 00841 TRACE("(%s)\n", debugstr_a(pszAuthType)); 00842 00843 if (!pszAuthType) 00844 return E_INVALIDARG; 00845 00846 len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszAuthType); 00847 szCommand = HeapAlloc(GetProcessHeap(), 0, len); 00848 if (!szCommand) 00849 return E_OUTOFMEMORY; 00850 00851 sprintf(szCommand, szCommandFormat, pszAuthType); 00852 00853 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand, 00854 SMTPTransport_CallbackReadResponseDoNothing); 00855 00856 HeapFree(GetProcessHeap(), 0, szCommand); 00857 return hr; 00858 } 00859 00860 static HRESULT WINAPI SMTPTransport_CommandQUIT(ISMTPTransport2 *iface) 00861 { 00862 SMTPTransport *This = (SMTPTransport *)iface; 00863 00864 TRACE("()\n"); 00865 00866 InternetTransport_ChangeStatus(&This->InetTransport, IXP_DISCONNECTING); 00867 return InternetTransport_DoCommand(&This->InetTransport, "QUIT\n", 00868 SMTPTransport_CallbackDisconnect); 00869 } 00870 00871 static HRESULT WINAPI SMTPTransport_CommandRSET(ISMTPTransport2 *iface) 00872 { 00873 SMTPTransport *This = (SMTPTransport *)iface; 00874 00875 TRACE("()\n"); 00876 00877 return InternetTransport_DoCommand(&This->InetTransport, "RSET\n", 00878 SMTPTransport_CallbackReadResponseDoNothing); 00879 } 00880 00881 static HRESULT WINAPI SMTPTransport_CommandDATA(ISMTPTransport2 *iface) 00882 { 00883 SMTPTransport *This = (SMTPTransport *)iface; 00884 00885 TRACE("()\n"); 00886 00887 return InternetTransport_DoCommand(&This->InetTransport, "DATA\n", 00888 SMTPTransport_CallbackReadDATAResponse); 00889 } 00890 00891 static HRESULT WINAPI SMTPTransport_CommandDOT(ISMTPTransport2 *iface) 00892 { 00893 FIXME("()\n"); 00894 return E_NOTIMPL; 00895 } 00896 00897 static HRESULT WINAPI SMTPTransport_SendDataStream(ISMTPTransport2 *iface, 00898 IStream *pStream, ULONG cbSize) 00899 { 00900 FIXME("(%p, %d)\n", pStream, cbSize); 00901 return E_NOTIMPL; 00902 } 00903 00904 static HRESULT WINAPI SMTPTransport_SetWindow(ISMTPTransport2 *iface) 00905 { 00906 FIXME("()\n"); 00907 return E_NOTIMPL; 00908 } 00909 00910 static HRESULT WINAPI SMTPTransport_ResetWindow(ISMTPTransport2 *iface) 00911 { 00912 FIXME("()\n"); 00913 return E_NOTIMPL; 00914 } 00915 00916 static HRESULT WINAPI SMTPTransport_SendMessage2(ISMTPTransport2 *iface, LPSMTPMESSAGE2 pMessage) 00917 { 00918 FIXME("(%p)\n", pMessage); 00919 return E_NOTIMPL; 00920 } 00921 00922 static HRESULT WINAPI SMTPTransport_CommandRCPT2(ISMTPTransport2 *iface, LPSTR pszEmailTo, 00923 INETADDRTYPE atDSN) 00924 { 00925 FIXME("(%s, %u)\n", pszEmailTo, atDSN); 00926 return E_NOTIMPL; 00927 } 00928 00929 static const ISMTPTransport2Vtbl SMTPTransport2Vtbl = 00930 { 00931 SMTPTransport_QueryInterface, 00932 SMTPTransport_AddRef, 00933 SMTPTransport_Release, 00934 SMTPTransport_GetServerInfo, 00935 SMTPTransport_GetIXPType, 00936 SMTPTransport_IsState, 00937 SMTPTransport_InetServerFromAccount, 00938 SMTPTransport_Connect, 00939 SMTPTransport_HandsOffCallback, 00940 SMTPTransport_Disconnect, 00941 SMTPTransport_DropConnection, 00942 SMTPTransport_GetStatus, 00943 SMTPTransport_InitNew, 00944 SMTPTransport_SendMessage, 00945 SMTPTransport_CommandMAIL, 00946 SMTPTransport_CommandRCPT, 00947 SMTPTransport_CommandEHLO, 00948 SMTPTransport_CommandHELO, 00949 SMTPTransport_CommandAUTH, 00950 SMTPTransport_CommandQUIT, 00951 SMTPTransport_CommandRSET, 00952 SMTPTransport_CommandDATA, 00953 SMTPTransport_CommandDOT, 00954 SMTPTransport_SendDataStream, 00955 SMTPTransport_SetWindow, 00956 SMTPTransport_ResetWindow, 00957 SMTPTransport_SendMessage2, 00958 SMTPTransport_CommandRCPT2 00959 }; 00960 00961 HRESULT WINAPI CreateSMTPTransport(ISMTPTransport **ppTransport) 00962 { 00963 HRESULT hr; 00964 SMTPTransport *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 00965 if (!This) 00966 return E_OUTOFMEMORY; 00967 00968 This->InetTransport.u.vtblSMTP2 = &SMTPTransport2Vtbl; 00969 This->refs = 0; 00970 This->fESMTP = FALSE; 00971 hr = InternetTransport_Init(&This->InetTransport); 00972 if (FAILED(hr)) 00973 { 00974 HeapFree(GetProcessHeap(), 0, This); 00975 return hr; 00976 } 00977 00978 *ppTransport = (ISMTPTransport *)&This->InetTransport.u.vtblSMTP2; 00979 ISMTPTransport_AddRef(*ppTransport); 00980 00981 return S_OK; 00982 } 00983 00984 00985 static HRESULT WINAPI SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface, 00986 REFIID riid, LPVOID *ppv) 00987 { 00988 *ppv = NULL; 00989 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) 00990 { 00991 *ppv = iface; 00992 IUnknown_AddRef(iface); 00993 return S_OK; 00994 } 00995 return E_NOINTERFACE; 00996 } 00997 00998 static ULONG WINAPI SMTPTransportCF_AddRef(LPCLASSFACTORY iface) 00999 { 01000 return 2; /* non-heap based object */ 01001 } 01002 01003 static ULONG WINAPI SMTPTransportCF_Release(LPCLASSFACTORY iface) 01004 { 01005 return 1; /* non-heap based object */ 01006 } 01007 01008 static HRESULT WINAPI SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface, 01009 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) 01010 { 01011 HRESULT hr; 01012 ISMTPTransport *pSmtpTransport; 01013 01014 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); 01015 01016 *ppv = NULL; 01017 01018 if (pUnk) 01019 return CLASS_E_NOAGGREGATION; 01020 01021 hr = CreateSMTPTransport(&pSmtpTransport); 01022 if (FAILED(hr)) 01023 return hr; 01024 01025 hr = ISMTPTransport_QueryInterface(pSmtpTransport, riid, ppv); 01026 ISMTPTransport_Release(pSmtpTransport); 01027 01028 return hr; 01029 } 01030 01031 static HRESULT WINAPI SMTPTransportCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) 01032 { 01033 FIXME("(%d)\n",fLock); 01034 return S_OK; 01035 } 01036 01037 static const IClassFactoryVtbl SMTPTransportCFVtbl = 01038 { 01039 SMTPTransportCF_QueryInterface, 01040 SMTPTransportCF_AddRef, 01041 SMTPTransportCF_Release, 01042 SMTPTransportCF_CreateInstance, 01043 SMTPTransportCF_LockServer 01044 }; 01045 static const IClassFactoryVtbl *SMTPTransportCF = &SMTPTransportCFVtbl; 01046 01047 HRESULT SMTPTransportCF_Create(REFIID riid, LPVOID *ppv) 01048 { 01049 return IClassFactory_QueryInterface((IClassFactory *)&SMTPTransportCF, riid, ppv); 01050 } Generated on Sun May 27 2012 04:24:09 for ReactOS by
1.7.6.1
|