[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