4 * Copyright 2006 Robert Shearman for CodeWeavers
5 * Copyright 2008 Hans Leidekker for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define WIN32_NO_STATUS
25 #define COM_NO_WINDOWS_H
35 //#include "winuser.h"
38 #include <wine/debug.h>
40 #include "inetcomm_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
46 InternetTransport InetTransport
;
49 SMTPMESSAGE pending_message
;
51 ULONG ulCurrentAddressIndex
;
54 static HRESULT
SMTPTransport_ParseResponse(SMTPTransport
*This
, char *pszResponse
, SMTPRESPONSE
*pResponse
)
56 HRESULT hrServerError
;
58 TRACE("response: %s\n", debugstr_a(pszResponse
));
60 if (!isdigit(*pszResponse
))
61 return IXP_E_SMTP_RESPONSE_ERROR
;
62 pResponse
->pTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
63 pResponse
->rIxpResult
.pszResponse
= pszResponse
;
64 pResponse
->rIxpResult
.dwSocketError
= 0;
65 pResponse
->rIxpResult
.uiServerError
= strtol(pszResponse
, &pszResponse
, 10);
66 if (*pszResponse
== '-')
68 pResponse
->fDone
= FALSE
;
72 pResponse
->fDone
= TRUE
;
74 switch (pResponse
->rIxpResult
.uiServerError
)
76 case 211: hrServerError
= IXP_E_SMTP_211_SYSTEM_STATUS
; break;
77 case 214: hrServerError
= IXP_E_SMTP_214_HELP_MESSAGE
; break;
78 case 220: hrServerError
= IXP_E_SMTP_220_READY
; break;
79 case 221: hrServerError
= IXP_E_SMTP_221_CLOSING
; break;
80 case 245: hrServerError
= IXP_E_SMTP_245_AUTH_SUCCESS
; break;
81 case 250: hrServerError
= IXP_E_SMTP_250_MAIL_ACTION_OKAY
; break;
82 case 251: hrServerError
= IXP_E_SMTP_251_FORWARDING_MAIL
; break;
83 case 334: hrServerError
= IXP_E_SMTP_334_AUTH_READY_RESPONSE
; break;
84 case 354: hrServerError
= IXP_E_SMTP_354_START_MAIL_INPUT
; break;
85 case 421: hrServerError
= IXP_E_SMTP_421_NOT_AVAILABLE
; break;
86 case 450: hrServerError
= IXP_E_SMTP_450_MAILBOX_BUSY
; break;
87 case 451: hrServerError
= IXP_E_SMTP_451_ERROR_PROCESSING
; break;
88 case 452: hrServerError
= IXP_E_SMTP_452_NO_SYSTEM_STORAGE
; break;
89 case 454: hrServerError
= IXP_E_SMTP_454_STARTTLS_FAILED
; break;
90 case 500: hrServerError
= IXP_E_SMTP_500_SYNTAX_ERROR
; break;
91 case 501: hrServerError
= IXP_E_SMTP_501_PARAM_SYNTAX
; break;
92 case 502: hrServerError
= IXP_E_SMTP_502_COMMAND_NOTIMPL
; break;
93 case 503: hrServerError
= IXP_E_SMTP_503_COMMAND_SEQ
; break;
94 case 504: hrServerError
= IXP_E_SMTP_504_COMMAND_PARAM_NOTIMPL
; break;
95 case 530: hrServerError
= IXP_E_SMTP_530_STARTTLS_REQUIRED
; break;
96 case 550: hrServerError
= IXP_E_SMTP_550_MAILBOX_NOT_FOUND
; break;
97 case 551: hrServerError
= IXP_E_SMTP_551_USER_NOT_LOCAL
; break;
98 case 552: hrServerError
= IXP_E_SMTP_552_STORAGE_OVERFLOW
; break;
99 case 553: hrServerError
= IXP_E_SMTP_553_MAILBOX_NAME_SYNTAX
; break;
100 case 554: hrServerError
= IXP_E_SMTP_554_TRANSACT_FAILED
; break;
102 hrServerError
= IXP_E_SMTP_RESPONSE_ERROR
;
105 pResponse
->rIxpResult
.hrResult
= hrServerError
;
106 pResponse
->rIxpResult
.hrServerError
= hrServerError
;
108 if (This
->InetTransport
.pCallback
&& This
->InetTransport
.fCommandLogging
)
110 ITransportCallback_OnCommand(This
->InetTransport
.pCallback
, CMD_RESP
,
111 pResponse
->rIxpResult
.pszResponse
, hrServerError
,
112 (IInternetTransport
*)&This
->InetTransport
.u
.vtbl
);
117 static void SMTPTransport_CallbackDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
122 static void SMTPTransport_CallbackReadResponseDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
124 SMTPTransport
*This
= (SMTPTransport
*)iface
;
127 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackDoNothing
);
130 static void SMTPTransport_CallbackProcessDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
132 SMTPTransport
*This
= (SMTPTransport
*)iface
;
133 SMTPRESPONSE response
= { 0 };
138 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
141 /* FIXME: handle error */
145 response
.command
= SMTP_DATA
;
146 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
148 if (FAILED(response
.rIxpResult
.hrServerError
))
150 ERR("server error: %s\n", debugstr_a(pBuffer
));
151 /* FIXME: handle error */
156 static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
158 SMTPTransport
*This
= (SMTPTransport
*)iface
;
161 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessDATAResponse
);
164 static void SMTPTransport_CallbackProcessMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
166 SMTPTransport
*This
= (SMTPTransport
*)iface
;
167 SMTPRESPONSE response
= { 0 };
172 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
175 /* FIXME: handle error */
179 response
.command
= SMTP_MAIL
;
180 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
182 if (FAILED(response
.rIxpResult
.hrServerError
))
184 ERR("server error: %s\n", debugstr_a(pBuffer
));
185 /* FIXME: handle error */
190 static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
192 SMTPTransport
*This
= (SMTPTransport
*)iface
;
195 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessMAILResponse
);
198 static void SMTPTransport_CallbackProcessRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
200 SMTPTransport
*This
= (SMTPTransport
*)iface
;
201 SMTPRESPONSE response
= { 0 };
206 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
207 This
->addrlist
= NULL
;
209 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
212 /* FIXME: handle error */
216 response
.command
= SMTP_RCPT
;
217 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
219 if (FAILED(response
.rIxpResult
.hrServerError
))
221 ERR("server error: %s\n", debugstr_a(pBuffer
));
222 /* FIXME: handle error */
227 static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
229 SMTPTransport
*This
= (SMTPTransport
*)iface
;
232 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessRCPTResponse
);
235 static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
237 SMTPTransport
*This
= (SMTPTransport
*)iface
;
238 SMTPRESPONSE response
= { 0 };
243 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
246 /* FIXME: handle error */
250 response
.command
= This
->fESMTP
? SMTP_EHLO
: SMTP_HELO
;
251 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
253 if (FAILED(response
.rIxpResult
.hrServerError
))
255 ERR("server error: %s\n", debugstr_a(pBuffer
));
256 /* FIXME: handle error */
262 InternetTransport_ReadLine(&This
->InetTransport
,
263 SMTPTransport_CallbackProcessHelloResp
);
267 /* FIXME: try to authorize */
269 /* always changed to this status, even if authorization not support on server */
270 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_AUTHORIZED
);
271 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_CONNECTED
);
273 memset(&response
, 0, sizeof(response
));
274 response
.command
= SMTP_CONNECTED
;
275 response
.fDone
= TRUE
;
276 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
279 static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
281 SMTPTransport
*This
= (SMTPTransport
*)iface
;
284 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessHelloResp
);
287 static void SMTPTransport_CallbackSendHello(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
289 SMTPTransport
*This
= (SMTPTransport
*)iface
;
290 SMTPRESPONSE response
= { 0 };
292 const char *pszHello
;
294 const char szHostName
[] = "localhost"; /* FIXME */
298 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
301 /* FIXME: handle error */
305 response
.command
= SMTP_BANNER
;
306 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
308 if (FAILED(response
.rIxpResult
.hrServerError
))
310 ERR("server error: %s\n", debugstr_a(pBuffer
));
311 /* FIXME: handle error */
315 TRACE("(%s)\n", pBuffer
);
317 This
->fESMTP
= strstr(response
.rIxpResult
.pszResponse
, "ESMTP") &&
318 This
->InetTransport
.ServerInfo
.dwFlags
& (ISF_SSLONSAMEPORT
|ISF_QUERYDSNSUPPORT
|ISF_QUERYAUTHSUPPORT
);
325 pszCommand
= HeapAlloc(GetProcessHeap(), 0, strlen(pszHello
) + strlen(szHostName
) + 2);
326 strcpy(pszCommand
, pszHello
);
327 strcat(pszCommand
, szHostName
);
328 pszCommand
[strlen(pszCommand
)+1] = '\0';
329 pszCommand
[strlen(pszCommand
)] = '\n';
331 InternetTransport_DoCommand(&This
->InetTransport
, pszCommand
,
332 SMTPTransport_CallbackRecvHelloResp
);
334 HeapFree(GetProcessHeap(), 0, pszCommand
);
337 static void SMTPTransport_CallbackDisconnect(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
339 SMTPTransport
*This
= (SMTPTransport
*)iface
;
340 SMTPRESPONSE response
;
347 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
350 /* FIXME: handle error */
354 if (FAILED(response
.rIxpResult
.hrServerError
))
356 ERR("server error: %s\n", debugstr_a(pBuffer
));
357 /* FIXME: handle error */
361 InternetTransport_DropConnection(&This
->InetTransport
);
364 static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
366 SMTPTransport
*This
= (SMTPTransport
*)iface
;
367 SMTPRESPONSE response
= { 0 };
372 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
375 /* FIXME: handle error */
379 if (FAILED(response
.rIxpResult
.hrServerError
))
381 ERR("server error: %s\n", debugstr_a(pBuffer
));
382 /* FIXME: handle error */
386 response
.command
= SMTP_SEND_MESSAGE
;
387 response
.rIxpResult
.hrResult
= S_OK
;
388 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
391 static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
393 SMTPTransport
*This
= (SMTPTransport
*)iface
;
394 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageProcessResponse
);
397 static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
399 SMTPTransport
*This
= (SMTPTransport
*)iface
;
401 IStream_Release(This
->pending_message
.pstmMsg
);
402 InternetTransport_DoCommand(&This
->InetTransport
, "\n.\n",
403 SMTPTransport_CallbackMessageReadResponse
);
406 static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
408 SMTPTransport
*This
= (SMTPTransport
*)iface
;
409 SMTPRESPONSE response
;
416 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
419 /* FIXME: handle error */
423 if (FAILED(response
.rIxpResult
.hrServerError
))
425 ERR("server error: %s\n", debugstr_a(pBuffer
));
426 /* FIXME: handle error */
430 pszBuffer
= HeapAlloc(GetProcessHeap(), 0, This
->pending_message
.cbSize
);
431 hr
= IStream_Read(This
->pending_message
.pstmMsg
, pszBuffer
, This
->pending_message
.cbSize
, NULL
);
434 /* FIXME: handle error */
437 cbSize
= This
->pending_message
.cbSize
;
439 /* FIXME: map "\n.\n" to "\n..\n", reallocate memory, update cbSize */
441 /* FIXME: properly stream the message rather than writing it all at once */
443 hr
= InternetTransport_Write(&This
->InetTransport
, pszBuffer
, cbSize
,
444 SMTPTransport_CallbackMessageSendDOT
);
446 HeapFree(GetProcessHeap(), 0, pszBuffer
);
449 static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
451 SMTPTransport
*This
= (SMTPTransport
*)iface
;
454 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendDataStream
);
457 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
);
459 static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
461 SMTPTransport
*This
= (SMTPTransport
*)iface
;
464 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
467 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
469 SMTPTransport
*This
= (SMTPTransport
*)iface
;
470 SMTPRESPONSE response
;
475 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
478 /* FIXME: handle error */
482 if (FAILED(response
.rIxpResult
.hrServerError
))
484 ERR("server error: %s\n", debugstr_a(pBuffer
));
485 /* FIXME: handle error */
489 for (; This
->ulCurrentAddressIndex
< This
->pending_message
.rAddressList
.cAddress
; This
->ulCurrentAddressIndex
++)
491 TRACE("address[%d]: %s\n", This
->ulCurrentAddressIndex
,
492 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
494 if ((This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
496 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
498 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ +
499 strlen(This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
501 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
505 sprintf(szCommand
, szCommandFormat
,
506 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
508 This
->ulCurrentAddressIndex
++;
509 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
510 SMTPTransport_CallbackMessageReadToResponse
);
512 HeapFree(GetProcessHeap(), 0, szCommand
);
517 hr
= InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
518 SMTPTransport_CallbackMessageReadDataResponse
);
521 static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
523 SMTPTransport
*This
= (SMTPTransport
*)iface
;
526 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
529 static HRESULT WINAPI
SMTPTransport_QueryInterface(ISMTPTransport2
*iface
, REFIID riid
, void **ppv
)
531 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
533 if (IsEqualIID(riid
, &IID_IUnknown
) ||
534 IsEqualIID(riid
, &IID_IInternetTransport
) ||
535 IsEqualIID(riid
, &IID_ISMTPTransport
) ||
536 IsEqualIID(riid
, &IID_ISMTPTransport2
))
539 IUnknown_AddRef(iface
);
543 FIXME("no interface for %s\n", debugstr_guid(riid
));
544 return E_NOINTERFACE
;
547 static ULONG WINAPI
SMTPTransport_AddRef(ISMTPTransport2
*iface
)
549 SMTPTransport
*This
= (SMTPTransport
*)iface
;
550 return InterlockedIncrement((LONG
*)&This
->refs
);
553 static ULONG WINAPI
SMTPTransport_Release(ISMTPTransport2
*iface
)
555 SMTPTransport
*This
= (SMTPTransport
*)iface
;
556 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
559 TRACE("destroying %p\n", This
);
560 if (This
->InetTransport
.Status
!= IXP_DISCONNECTED
)
561 InternetTransport_DropConnection(&This
->InetTransport
);
563 if (This
->InetTransport
.pCallback
) ITransportCallback_Release(This
->InetTransport
.pCallback
);
564 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
565 HeapFree(GetProcessHeap(), 0, This
);
570 static HRESULT WINAPI
SMTPTransport_GetServerInfo(ISMTPTransport2
*iface
,
571 LPINETSERVER pInetServer
)
573 SMTPTransport
*This
= (SMTPTransport
*)iface
;
575 TRACE("(%p)\n", pInetServer
);
576 return InternetTransport_GetServerInfo(&This
->InetTransport
, pInetServer
);
579 static IXPTYPE WINAPI
SMTPTransport_GetIXPType(ISMTPTransport2
*iface
)
585 static HRESULT WINAPI
SMTPTransport_IsState(ISMTPTransport2
*iface
,
588 FIXME("(%d): stub\n", isstate
);
592 static HRESULT WINAPI
SMTPTransport_InetServerFromAccount(
593 ISMTPTransport2
*iface
, IImnAccount
*pAccount
, LPINETSERVER pInetServer
)
595 SMTPTransport
*This
= (SMTPTransport
*)iface
;
597 TRACE("(%p, %p)\n", pAccount
, pInetServer
);
598 return InternetTransport_InetServerFromAccount(&This
->InetTransport
, pAccount
, pInetServer
);
601 static HRESULT WINAPI
SMTPTransport_Connect(ISMTPTransport2
*iface
,
602 LPINETSERVER pInetServer
, boolean fAuthenticate
, boolean fCommandLogging
)
604 SMTPTransport
*This
= (SMTPTransport
*)iface
;
607 TRACE("(%p, %s, %s)\n", pInetServer
, fAuthenticate
? "TRUE" : "FALSE", fCommandLogging
? "TRUE" : "FALSE");
609 hr
= InternetTransport_Connect(&This
->InetTransport
, pInetServer
, fAuthenticate
, fCommandLogging
);
613 /* this starts the state machine, which continues in SMTPTransport_CallbackSendHELO */
614 return InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackSendHello
);
617 static HRESULT WINAPI
SMTPTransport_HandsOffCallback(ISMTPTransport2
*iface
)
619 SMTPTransport
*This
= (SMTPTransport
*)iface
;
622 return InternetTransport_HandsOffCallback(&This
->InetTransport
);
625 static HRESULT WINAPI
SMTPTransport_Disconnect(ISMTPTransport2
*iface
)
628 return ISMTPTransport2_CommandQUIT(iface
);
631 static HRESULT WINAPI
SMTPTransport_DropConnection(ISMTPTransport2
*iface
)
633 SMTPTransport
*This
= (SMTPTransport
*)iface
;
636 return InternetTransport_DropConnection(&This
->InetTransport
);
639 static HRESULT WINAPI
SMTPTransport_GetStatus(ISMTPTransport2
*iface
,
640 IXPSTATUS
*pCurrentStatus
)
642 SMTPTransport
*This
= (SMTPTransport
*)iface
;
645 return InternetTransport_GetStatus(&This
->InetTransport
, pCurrentStatus
);
648 static HRESULT WINAPI
SMTPTransport_InitNew(ISMTPTransport2
*iface
,
649 LPSTR pszLogFilePath
, ISMTPCallback
*pCallback
)
651 SMTPTransport
*This
= (SMTPTransport
*)iface
;
653 TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath
), pCallback
);
659 FIXME("not using log file of %s, use Wine debug logging instead\n",
660 debugstr_a(pszLogFilePath
));
662 ISMTPCallback_AddRef(pCallback
);
663 This
->InetTransport
.pCallback
= (ITransportCallback
*)pCallback
;
664 This
->InetTransport
.fInitialised
= TRUE
;
669 static HRESULT WINAPI
SMTPTransport_SendMessage(ISMTPTransport2
*iface
,
670 LPSMTPMESSAGE pMessage
)
672 SMTPTransport
*This
= (SMTPTransport
*)iface
;
674 LPSTR pszFromAddress
= NULL
;
675 const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
680 TRACE("(%p)\n", pMessage
);
682 This
->pending_message
= *pMessage
;
683 IStream_AddRef(pMessage
->pstmMsg
);
685 size
= pMessage
->rAddressList
.cAddress
* sizeof(INETADDR
);
686 This
->addrlist
= HeapAlloc(GetProcessHeap(), 0, size
);
688 return E_OUTOFMEMORY
;
690 memcpy(This
->addrlist
, pMessage
->rAddressList
.prgAddress
, size
);
691 This
->pending_message
.rAddressList
.prgAddress
= This
->addrlist
;
692 This
->ulCurrentAddressIndex
= 0;
694 for (i
= 0; i
< pMessage
->rAddressList
.cAddress
; i
++)
696 if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_FROM
)
698 TRACE("address[%d]: ADDR_FROM, %s\n", i
,
699 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
700 pszFromAddress
= pMessage
->rAddressList
.prgAddress
[i
].szEmail
;
702 else if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
704 TRACE("address[%d]: ADDR_TO, %s\n", i
,
705 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
711 SMTPRESPONSE response
;
712 memset(&response
, 0, sizeof(response
));
713 response
.command
= SMTP_SEND_MESSAGE
;
714 response
.fDone
= TRUE
;
715 response
.pTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
716 response
.rIxpResult
.hrResult
= IXP_E_SMTP_NO_SENDER
;
717 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
720 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszFromAddress
);
722 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
724 return E_OUTOFMEMORY
;
726 sprintf(szCommand
, szCommandFormat
, pszFromAddress
);
728 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
729 SMTPTransport_CallbackMessageReadFromResponse
);
734 static HRESULT WINAPI
SMTPTransport_CommandMAIL(ISMTPTransport2
*iface
, LPSTR pszEmailFrom
)
736 SMTPTransport
*This
= (SMTPTransport
*)iface
;
737 const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
742 TRACE("(%s)\n", debugstr_a(pszEmailFrom
));
747 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailFrom
);
748 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
750 return E_OUTOFMEMORY
;
752 sprintf(szCommand
, szCommandFormat
, pszEmailFrom
);
754 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
755 SMTPTransport_CallbackReadMAILResponse
);
757 HeapFree(GetProcessHeap(), 0, szCommand
);
761 static HRESULT WINAPI
SMTPTransport_CommandRCPT(ISMTPTransport2
*iface
, LPSTR pszEmailTo
)
763 SMTPTransport
*This
= (SMTPTransport
*)iface
;
764 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
769 TRACE("(%s)\n", debugstr_a(pszEmailTo
));
774 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailTo
);
775 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
777 return E_OUTOFMEMORY
;
779 sprintf(szCommand
, szCommandFormat
, pszEmailTo
);
781 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
782 SMTPTransport_CallbackReadRCPTResponse
);
784 HeapFree(GetProcessHeap(), 0, szCommand
);
788 static HRESULT WINAPI
SMTPTransport_CommandEHLO(ISMTPTransport2
*iface
)
790 SMTPTransport
*This
= (SMTPTransport
*)iface
;
791 const char szCommandFormat
[] = "EHLO %s\n";
792 const char szHostname
[] = "localhost"; /* FIXME */
794 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
799 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
801 return E_OUTOFMEMORY
;
803 sprintf(szCommand
, szCommandFormat
, szHostname
);
805 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
806 SMTPTransport_CallbackReadResponseDoNothing
);
808 HeapFree(GetProcessHeap(), 0, szCommand
);
812 static HRESULT WINAPI
SMTPTransport_CommandHELO(ISMTPTransport2
*iface
)
814 SMTPTransport
*This
= (SMTPTransport
*)iface
;
815 const char szCommandFormat
[] = "HELO %s\n";
816 const char szHostname
[] = "localhost"; /* FIXME */
818 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
823 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
825 return E_OUTOFMEMORY
;
827 sprintf(szCommand
, szCommandFormat
, szHostname
);
829 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
830 SMTPTransport_CallbackReadResponseDoNothing
);
832 HeapFree(GetProcessHeap(), 0, szCommand
);
836 static HRESULT WINAPI
SMTPTransport_CommandAUTH(ISMTPTransport2
*iface
,
839 SMTPTransport
*This
= (SMTPTransport
*)iface
;
840 const char szCommandFormat
[] = "AUTH %s\n";
845 TRACE("(%s)\n", debugstr_a(pszAuthType
));
850 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszAuthType
);
851 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
853 return E_OUTOFMEMORY
;
855 sprintf(szCommand
, szCommandFormat
, pszAuthType
);
857 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
858 SMTPTransport_CallbackReadResponseDoNothing
);
860 HeapFree(GetProcessHeap(), 0, szCommand
);
864 static HRESULT WINAPI
SMTPTransport_CommandQUIT(ISMTPTransport2
*iface
)
866 SMTPTransport
*This
= (SMTPTransport
*)iface
;
870 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_DISCONNECTING
);
871 return InternetTransport_DoCommand(&This
->InetTransport
, "QUIT\n",
872 SMTPTransport_CallbackDisconnect
);
875 static HRESULT WINAPI
SMTPTransport_CommandRSET(ISMTPTransport2
*iface
)
877 SMTPTransport
*This
= (SMTPTransport
*)iface
;
881 return InternetTransport_DoCommand(&This
->InetTransport
, "RSET\n",
882 SMTPTransport_CallbackReadResponseDoNothing
);
885 static HRESULT WINAPI
SMTPTransport_CommandDATA(ISMTPTransport2
*iface
)
887 SMTPTransport
*This
= (SMTPTransport
*)iface
;
891 return InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
892 SMTPTransport_CallbackReadDATAResponse
);
895 static HRESULT WINAPI
SMTPTransport_CommandDOT(ISMTPTransport2
*iface
)
901 static HRESULT WINAPI
SMTPTransport_SendDataStream(ISMTPTransport2
*iface
,
902 IStream
*pStream
, ULONG cbSize
)
904 FIXME("(%p, %d)\n", pStream
, cbSize
);
908 static HRESULT WINAPI
SMTPTransport_SetWindow(ISMTPTransport2
*iface
)
914 static HRESULT WINAPI
SMTPTransport_ResetWindow(ISMTPTransport2
*iface
)
920 static HRESULT WINAPI
SMTPTransport_SendMessage2(ISMTPTransport2
*iface
, LPSMTPMESSAGE2 pMessage
)
922 FIXME("(%p)\n", pMessage
);
926 static HRESULT WINAPI
SMTPTransport_CommandRCPT2(ISMTPTransport2
*iface
, LPSTR pszEmailTo
,
929 FIXME("(%s, %u)\n", pszEmailTo
, atDSN
);
933 static const ISMTPTransport2Vtbl SMTPTransport2Vtbl
=
935 SMTPTransport_QueryInterface
,
936 SMTPTransport_AddRef
,
937 SMTPTransport_Release
,
938 SMTPTransport_GetServerInfo
,
939 SMTPTransport_GetIXPType
,
940 SMTPTransport_IsState
,
941 SMTPTransport_InetServerFromAccount
,
942 SMTPTransport_Connect
,
943 SMTPTransport_HandsOffCallback
,
944 SMTPTransport_Disconnect
,
945 SMTPTransport_DropConnection
,
946 SMTPTransport_GetStatus
,
947 SMTPTransport_InitNew
,
948 SMTPTransport_SendMessage
,
949 SMTPTransport_CommandMAIL
,
950 SMTPTransport_CommandRCPT
,
951 SMTPTransport_CommandEHLO
,
952 SMTPTransport_CommandHELO
,
953 SMTPTransport_CommandAUTH
,
954 SMTPTransport_CommandQUIT
,
955 SMTPTransport_CommandRSET
,
956 SMTPTransport_CommandDATA
,
957 SMTPTransport_CommandDOT
,
958 SMTPTransport_SendDataStream
,
959 SMTPTransport_SetWindow
,
960 SMTPTransport_ResetWindow
,
961 SMTPTransport_SendMessage2
,
962 SMTPTransport_CommandRCPT2
965 HRESULT WINAPI
CreateSMTPTransport(ISMTPTransport
**ppTransport
)
968 SMTPTransport
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
970 return E_OUTOFMEMORY
;
972 This
->InetTransport
.u
.vtblSMTP2
= &SMTPTransport2Vtbl
;
974 This
->fESMTP
= FALSE
;
975 hr
= InternetTransport_Init(&This
->InetTransport
);
978 HeapFree(GetProcessHeap(), 0, This
);
982 *ppTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
983 ISMTPTransport_AddRef(*ppTransport
);
989 static HRESULT WINAPI
SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface
,
990 REFIID riid
, LPVOID
*ppv
)
993 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
996 IUnknown_AddRef(iface
);
999 return E_NOINTERFACE
;
1002 static ULONG WINAPI
SMTPTransportCF_AddRef(LPCLASSFACTORY iface
)
1004 return 2; /* non-heap based object */
1007 static ULONG WINAPI
SMTPTransportCF_Release(LPCLASSFACTORY iface
)
1009 return 1; /* non-heap based object */
1012 static HRESULT WINAPI
SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface
,
1013 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
1016 ISMTPTransport
*pSmtpTransport
;
1018 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
1023 return CLASS_E_NOAGGREGATION
;
1025 hr
= CreateSMTPTransport(&pSmtpTransport
);
1029 hr
= ISMTPTransport_QueryInterface(pSmtpTransport
, riid
, ppv
);
1030 ISMTPTransport_Release(pSmtpTransport
);
1035 static HRESULT WINAPI
SMTPTransportCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
1037 FIXME("(%d)\n",fLock
);
1041 static const IClassFactoryVtbl SMTPTransportCFVtbl
=
1043 SMTPTransportCF_QueryInterface
,
1044 SMTPTransportCF_AddRef
,
1045 SMTPTransportCF_Release
,
1046 SMTPTransportCF_CreateInstance
,
1047 SMTPTransportCF_LockServer
1049 static const IClassFactoryVtbl
*SMTPTransportCF
= &SMTPTransportCFVtbl
;
1051 HRESULT
SMTPTransportCF_Create(REFIID riid
, LPVOID
*ppv
)
1053 return IClassFactory_QueryInterface((IClassFactory
*)&SMTPTransportCF
, riid
, ppv
);