ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

smtptransport.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.