[01/14] inetcomm: Add an implementation of ISMTPTransport2::SendMessage.

Hans Leidekker hans at codeweavers.com
Fri Oct 31 07:50:08 CDT 2008


Written by Rob, but I made some small improvements.

Changelog
 Rob Shearman <rob at codeweavers.com>
 Add an implementation of ISMTPTransport2::SendMessage.

 -Hans

diff --git a/dlls/inetcomm/inetcomm_private.h b/dlls/inetcomm/inetcomm_private.h
index c9d8225..7752d69 100644
--- a/dlls/inetcomm/inetcomm_private.h
+++ b/dlls/inetcomm/inetcomm_private.h
@@ -68,7 +68,7 @@ HRESULT InternetTransport_ReadLine(InternetTransport *This,
 HRESULT InternetTransport_Write(InternetTransport *This, const char *pvData,
     int cbSize, INETXPORT_COMPLETION_FUNCTION fnCompletion);
 HRESULT InternetTransport_DoCommand(InternetTransport *This,
-    LPSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion);
+    LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion);
 
 BOOL InternetTransport_RegisterClass(HINSTANCE hInstance);
 void InternetTransport_UnregisterClass(HINSTANCE hInstance);
diff --git a/dlls/inetcomm/internettransport.c b/dlls/inetcomm/internettransport.c
index b6a5a4a..7cef414 100644
--- a/dlls/inetcomm/internettransport.c
+++ b/dlls/inetcomm/internettransport.c
@@ -275,7 +275,7 @@ HRESULT InternetTransport_Write(InternetTransport *This, const char *pvData,
 }
 
 HRESULT InternetTransport_DoCommand(InternetTransport *This,
-    LPSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion)
+    LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion)
 {
     if (This->Status == IXP_DISCONNECTED)
         return IXP_E_NOT_CONNECTED;
@@ -285,7 +285,7 @@ HRESULT InternetTransport_DoCommand(InternetTransport *This,
 
     if (This->pCallback && This->fCommandLogging)
     {
-        ITransportCallback_OnCommand(This->pCallback, CMD_SEND, pszCommand, 0,
+        ITransportCallback_OnCommand(This->pCallback, CMD_SEND, (LPSTR)pszCommand, 0,
             (IInternetTransport *)&This->u.vtbl);
     }
     return InternetTransport_Write(This, pszCommand, strlen(pszCommand), fnCompletion);
diff --git a/dlls/inetcomm/smtptransport.c b/dlls/inetcomm/smtptransport.c
index b3bc781..d7a3c30 100644
--- a/dlls/inetcomm/smtptransport.c
+++ b/dlls/inetcomm/smtptransport.c
@@ -42,6 +42,9 @@ typedef struct
     InternetTransport InetTransport;
     ULONG refs;
     BOOL fESMTP;
+    SMTPMESSAGE pending_message;
+    INETADDR *addrlist;
+    ULONG ulCurrentAddressIndex;
 } SMTPTransport;
 
 static HRESULT SMTPTransport_ParseResponse(SMTPTransport *This, char *pszResponse, SMTPRESPONSE *pResponse)
@@ -209,6 +212,171 @@ static void SMTPTransport_CallbackSendHello(IInternetTransport *iface, char *pBu
     HeapFree(GetProcessHeap(), 0, pszCommand);
 }
 
+static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
+{
+    SMTPTransport *This = (SMTPTransport *)iface;
+    SMTPRESPONSE response = { 0 };
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = SMTPTransport_ParseResponse(This, pBuffer, &response);
+    if (FAILED(hr))
+    {
+        /* FIXME: handle error */
+        return;
+    }
+
+    if (FAILED(response.rIxpResult.hrServerError))
+    {
+        ERR("server error: %s\n", debugstr_a(pBuffer));
+        /* FIXME: handle error */
+        return;
+    }
+
+    response.command = SMTP_SEND_MESSAGE;
+    response.rIxpResult.hrResult = S_OK;
+    ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
+}
+
+static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
+{
+    SMTPTransport *This = (SMTPTransport *)iface;
+    InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackMessageProcessResponse);
+}
+
+static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport *iface, char *pBuffer, int cbBuffer)
+{
+    SMTPTransport *This = (SMTPTransport *)iface;
+
+    IStream_Release(This->pending_message.pstmMsg);
+    InternetTransport_DoCommand(&This->InetTransport, "\n.\n",
+        SMTPTransport_CallbackMessageReadResponse);
+}
+
+static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport *iface, char *pBuffer, int cbBuffer)
+{
+    SMTPTransport *This = (SMTPTransport *)iface;
+    SMTPRESPONSE response;
+    HRESULT hr;
+    char *pszBuffer;
+    ULONG cbSize;
+
+    TRACE("\n");
+
+    hr = SMTPTransport_ParseResponse(This, pBuffer, &response);
+    if (FAILED(hr))
+    {
+        /* FIXME: handle error */
+        return;
+    }
+
+    if (FAILED(response.rIxpResult.hrServerError))
+    {
+        ERR("server error: %s\n", debugstr_a(pBuffer));
+        /* FIXME: handle error */
+        return;
+    }
+
+    pszBuffer = HeapAlloc(GetProcessHeap(), 0, This->pending_message.cbSize);
+    hr = IStream_Read(This->pending_message.pstmMsg, pszBuffer, This->pending_message.cbSize, NULL);
+    if (FAILED(hr))
+    {
+        /* FIXME: handle error */
+        return;
+    }
+    cbSize = This->pending_message.cbSize;
+
+    /* FIXME: map "\n.\n" to "\n..\n", reallocate memory, update cbSize */
+
+    /* FIXME: properly stream the message rather than writing it all at once */
+
+    hr = InternetTransport_Write(&This->InetTransport, pszBuffer, cbSize,
+        SMTPTransport_CallbackMessageSendDOT);
+
+    HeapFree(GetProcessHeap(), 0, pszBuffer);
+}
+
+static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
+{
+    SMTPTransport *This = (SMTPTransport *)iface;
+
+    TRACE("\n");
+    InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackMessageSendDataStream);
+}
+
+static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer);
+
+static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
+{
+    SMTPTransport *This = (SMTPTransport *)iface;
+
+    TRACE("\n");
+    InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackMessageSendTo);
+}
+
+static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer)
+{
+    SMTPTransport *This = (SMTPTransport *)iface;
+    SMTPRESPONSE response;
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = SMTPTransport_ParseResponse(This, pBuffer, &response);
+    if (FAILED(hr))
+    {
+        /* FIXME: handle error */
+        return;
+    }
+
+    if (FAILED(response.rIxpResult.hrServerError))
+    {
+        ERR("server error: %s\n", debugstr_a(pBuffer));
+        /* FIXME: handle error */
+        return;
+    }
+
+    for (; This->ulCurrentAddressIndex < This->pending_message.rAddressList.cAddress; This->ulCurrentAddressIndex++)
+    {
+        TRACE("address[%d]: %s\n", This->ulCurrentAddressIndex,
+            This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail);
+
+        if ((This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].addrtype & ADDR_TOFROM_MASK) == ADDR_TO)
+        {
+            const char szCommandFormat[] = "RCPT TO: <%s>\n";
+            char *szCommand;
+            int len = sizeof(szCommandFormat) - 2 /* "%s" */ +
+                strlen(This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail);
+
+            szCommand = HeapAlloc(GetProcessHeap(), 0, len);
+            if (!szCommand)
+                return;
+
+            sprintf(szCommand, szCommandFormat,
+                This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail);
+
+            This->ulCurrentAddressIndex++;
+            hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
+                SMTPTransport_CallbackMessageReadToResponse);
+
+            HeapFree(GetProcessHeap(), 0, szCommand);
+            return;
+        }
+    }
+
+    hr = InternetTransport_DoCommand(&This->InetTransport, "DATA\n",
+        SMTPTransport_CallbackMessageReadDataResponse);
+}
+
+static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
+{
+    SMTPTransport *This = (SMTPTransport *)iface;
+
+    TRACE("\n");
+    InternetTransport_ReadLine(&This->InetTransport, SMTPTransport_CallbackMessageSendTo);
+}
+
 static HRESULT WINAPI SMTPTransport_QueryInterface(ISMTPTransport2 *iface, REFIID riid, void **ppv)
 {
     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
@@ -244,6 +412,7 @@ static ULONG WINAPI SMTPTransport_Release(ISMTPTransport2 *iface)
             InternetTransport_DropConnection(&This->InetTransport);
 
         if (This->InetTransport.pCallback) ITransportCallback_Release(This->InetTransport.pCallback);
+        HeapFree(GetProcessHeap(), 0, This->addrlist);
         HeapFree(GetProcessHeap(), 0, This);
     }
     return refs;
@@ -349,8 +518,66 @@ static HRESULT WINAPI SMTPTransport_InitNew(ISMTPTransport2 *iface,
 static HRESULT WINAPI SMTPTransport_SendMessage(ISMTPTransport2 *iface,
     LPSMTPMESSAGE pMessage)
 {
-    FIXME("(%p)\n", pMessage);
-    return E_NOTIMPL;
+    SMTPTransport *This = (SMTPTransport *)iface;
+    ULONG i, size;
+    LPSTR pszFromAddress = NULL;
+    const char szCommandFormat[] = "MAIL FROM: <%s>\n";
+    char *szCommand;
+    int len;
+    HRESULT hr;
+
+    TRACE("(%p)\n", pMessage);
+
+    This->pending_message = *pMessage;
+    IStream_AddRef(pMessage->pstmMsg);
+
+    size = pMessage->rAddressList.cAddress * sizeof(INETADDR);
+    This->addrlist = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!This->addrlist)
+        return E_OUTOFMEMORY;
+
+    memcpy(This->addrlist, pMessage->rAddressList.prgAddress, size);
+    This->pending_message.rAddressList.prgAddress = This->addrlist;
+    This->ulCurrentAddressIndex = 0;
+
+    for (i = 0; i < pMessage->rAddressList.cAddress; i++)
+    {
+        if ((pMessage->rAddressList.prgAddress[i].addrtype & ADDR_TOFROM_MASK) == ADDR_FROM)
+        {
+            TRACE("address[%d]: ADDR_FROM, %s\n", i,
+                pMessage->rAddressList.prgAddress[i].szEmail);
+            pszFromAddress = pMessage->rAddressList.prgAddress[i].szEmail;
+        }
+        else if ((pMessage->rAddressList.prgAddress[i].addrtype & ADDR_TOFROM_MASK) == ADDR_TO)
+        {
+            TRACE("address[%d]: ADDR_TO, %s\n", i,
+                pMessage->rAddressList.prgAddress[i].szEmail);
+        }
+    }
+
+    if (!pszFromAddress)
+    {
+        SMTPRESPONSE response;
+        memset(&response, 0, sizeof(response));
+        response.command = SMTP_SEND_MESSAGE;
+        response.fDone = TRUE;
+        response.pTransport = (ISMTPTransport *)&This->InetTransport.u.vtblSMTP2;
+        response.rIxpResult.hrResult = IXP_E_SMTP_NO_SENDER;
+        ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
+        return S_OK;
+    }
+    len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszFromAddress);
+
+    szCommand = HeapAlloc(GetProcessHeap(), 0, len);
+    if (!szCommand)
+        return E_OUTOFMEMORY;
+
+    sprintf(szCommand, szCommandFormat, pszFromAddress);
+
+    hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
+        SMTPTransport_CallbackMessageReadFromResponse);
+
+    return hr;
 }
 
 static HRESULT WINAPI SMTPTransport_CommandMAIL(ISMTPTransport2 *iface, LPSTR pszEmailFrom)



More information about the wine-patches mailing list