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
34 #include "wine/debug.h"
36 #include "inetcomm_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
42 InternetTransport InetTransport
;
45 SMTPMESSAGE pending_message
;
47 ULONG ulCurrentAddressIndex
;
50 static HRESULT
SMTPTransport_ParseResponse(SMTPTransport
*This
, char *pszResponse
, SMTPRESPONSE
*pResponse
)
52 HRESULT hrServerError
;
54 TRACE("response: %s\n", debugstr_a(pszResponse
));
56 if (!isdigit(*pszResponse
))
57 return IXP_E_SMTP_RESPONSE_ERROR
;
58 pResponse
->pTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
59 pResponse
->rIxpResult
.pszResponse
= pszResponse
;
60 pResponse
->rIxpResult
.dwSocketError
= 0;
61 pResponse
->rIxpResult
.uiServerError
= strtol(pszResponse
, &pszResponse
, 10);
62 if (*pszResponse
== '-')
64 pResponse
->fDone
= FALSE
;
68 pResponse
->fDone
= TRUE
;
70 switch (pResponse
->rIxpResult
.uiServerError
)
72 case 211: hrServerError
= IXP_E_SMTP_211_SYSTEM_STATUS
; break;
73 case 214: hrServerError
= IXP_E_SMTP_214_HELP_MESSAGE
; break;
74 case 220: hrServerError
= IXP_E_SMTP_220_READY
; break;
75 case 221: hrServerError
= IXP_E_SMTP_221_CLOSING
; break;
76 case 245: hrServerError
= IXP_E_SMTP_245_AUTH_SUCCESS
; break;
77 case 250: hrServerError
= IXP_E_SMTP_250_MAIL_ACTION_OKAY
; break;
78 case 251: hrServerError
= IXP_E_SMTP_251_FORWARDING_MAIL
; break;
79 case 334: hrServerError
= IXP_E_SMTP_334_AUTH_READY_RESPONSE
; break;
80 case 354: hrServerError
= IXP_E_SMTP_354_START_MAIL_INPUT
; break;
81 case 421: hrServerError
= IXP_E_SMTP_421_NOT_AVAILABLE
; break;
82 case 450: hrServerError
= IXP_E_SMTP_450_MAILBOX_BUSY
; break;
83 case 451: hrServerError
= IXP_E_SMTP_451_ERROR_PROCESSING
; break;
84 case 452: hrServerError
= IXP_E_SMTP_452_NO_SYSTEM_STORAGE
; break;
85 case 454: hrServerError
= IXP_E_SMTP_454_STARTTLS_FAILED
; break;
86 case 500: hrServerError
= IXP_E_SMTP_500_SYNTAX_ERROR
; break;
87 case 501: hrServerError
= IXP_E_SMTP_501_PARAM_SYNTAX
; break;
88 case 502: hrServerError
= IXP_E_SMTP_502_COMMAND_NOTIMPL
; break;
89 case 503: hrServerError
= IXP_E_SMTP_503_COMMAND_SEQ
; break;
90 case 504: hrServerError
= IXP_E_SMTP_504_COMMAND_PARAM_NOTIMPL
; break;
91 case 530: hrServerError
= IXP_E_SMTP_530_STARTTLS_REQUIRED
; break;
92 case 550: hrServerError
= IXP_E_SMTP_550_MAILBOX_NOT_FOUND
; break;
93 case 551: hrServerError
= IXP_E_SMTP_551_USER_NOT_LOCAL
; break;
94 case 552: hrServerError
= IXP_E_SMTP_552_STORAGE_OVERFLOW
; break;
95 case 553: hrServerError
= IXP_E_SMTP_553_MAILBOX_NAME_SYNTAX
; break;
96 case 554: hrServerError
= IXP_E_SMTP_554_TRANSACT_FAILED
; break;
98 hrServerError
= IXP_E_SMTP_RESPONSE_ERROR
;
101 pResponse
->rIxpResult
.hrResult
= hrServerError
;
102 pResponse
->rIxpResult
.hrServerError
= hrServerError
;
104 if (This
->InetTransport
.pCallback
&& This
->InetTransport
.fCommandLogging
)
106 ITransportCallback_OnCommand(This
->InetTransport
.pCallback
, CMD_RESP
,
107 pResponse
->rIxpResult
.pszResponse
, hrServerError
,
108 (IInternetTransport
*)&This
->InetTransport
.u
.vtbl
);
113 static void SMTPTransport_CallbackDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
118 static void SMTPTransport_CallbackReadResponseDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
120 SMTPTransport
*This
= (SMTPTransport
*)iface
;
123 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackDoNothing
);
126 static void SMTPTransport_CallbackProcessDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
128 SMTPTransport
*This
= (SMTPTransport
*)iface
;
129 SMTPRESPONSE response
= { 0 };
134 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
137 /* FIXME: handle error */
141 response
.command
= SMTP_DATA
;
142 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
144 if (FAILED(response
.rIxpResult
.hrServerError
))
146 ERR("server error: %s\n", debugstr_a(pBuffer
));
147 /* FIXME: handle error */
152 static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
154 SMTPTransport
*This
= (SMTPTransport
*)iface
;
157 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessDATAResponse
);
160 static void SMTPTransport_CallbackProcessMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
162 SMTPTransport
*This
= (SMTPTransport
*)iface
;
163 SMTPRESPONSE response
= { 0 };
168 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
171 /* FIXME: handle error */
175 response
.command
= SMTP_MAIL
;
176 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
178 if (FAILED(response
.rIxpResult
.hrServerError
))
180 ERR("server error: %s\n", debugstr_a(pBuffer
));
181 /* FIXME: handle error */
186 static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
188 SMTPTransport
*This
= (SMTPTransport
*)iface
;
191 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessMAILResponse
);
194 static void SMTPTransport_CallbackProcessRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
196 SMTPTransport
*This
= (SMTPTransport
*)iface
;
197 SMTPRESPONSE response
= { 0 };
202 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
203 This
->addrlist
= NULL
;
205 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
208 /* FIXME: handle error */
212 response
.command
= SMTP_RCPT
;
213 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
215 if (FAILED(response
.rIxpResult
.hrServerError
))
217 ERR("server error: %s\n", debugstr_a(pBuffer
));
218 /* FIXME: handle error */
223 static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
225 SMTPTransport
*This
= (SMTPTransport
*)iface
;
228 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessRCPTResponse
);
231 static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
233 SMTPTransport
*This
= (SMTPTransport
*)iface
;
234 SMTPRESPONSE response
= { 0 };
239 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
242 /* FIXME: handle error */
246 response
.command
= This
->fESMTP
? SMTP_EHLO
: SMTP_HELO
;
247 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
249 if (FAILED(response
.rIxpResult
.hrServerError
))
251 ERR("server error: %s\n", debugstr_a(pBuffer
));
252 /* FIXME: handle error */
258 InternetTransport_ReadLine(&This
->InetTransport
,
259 SMTPTransport_CallbackProcessHelloResp
);
263 /* FIXME: try to authorize */
265 /* always changed to this status, even if authorization not support on server */
266 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_AUTHORIZED
);
267 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_CONNECTED
);
269 memset(&response
, 0, sizeof(response
));
270 response
.command
= SMTP_CONNECTED
;
271 response
.fDone
= TRUE
;
272 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
275 static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
277 SMTPTransport
*This
= (SMTPTransport
*)iface
;
280 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessHelloResp
);
283 static void SMTPTransport_CallbackSendHello(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
285 SMTPTransport
*This
= (SMTPTransport
*)iface
;
286 SMTPRESPONSE response
= { 0 };
288 const char *pszHello
;
290 const char szHostName
[] = "localhost"; /* FIXME */
294 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
297 /* FIXME: handle error */
301 response
.command
= SMTP_BANNER
;
302 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
304 if (FAILED(response
.rIxpResult
.hrServerError
))
306 ERR("server error: %s\n", debugstr_a(pBuffer
));
307 /* FIXME: handle error */
311 TRACE("(%s)\n", pBuffer
);
313 This
->fESMTP
= strstr(response
.rIxpResult
.pszResponse
, "ESMTP") &&
314 This
->InetTransport
.ServerInfo
.dwFlags
& (ISF_SSLONSAMEPORT
|ISF_QUERYDSNSUPPORT
|ISF_QUERYAUTHSUPPORT
);
321 pszCommand
= HeapAlloc(GetProcessHeap(), 0, strlen(pszHello
) + strlen(szHostName
) + 2);
322 strcpy(pszCommand
, pszHello
);
323 strcat(pszCommand
, szHostName
);
324 pszCommand
[strlen(pszCommand
)+1] = '\0';
325 pszCommand
[strlen(pszCommand
)] = '\n';
327 InternetTransport_DoCommand(&This
->InetTransport
, pszCommand
,
328 SMTPTransport_CallbackRecvHelloResp
);
330 HeapFree(GetProcessHeap(), 0, pszCommand
);
333 static void SMTPTransport_CallbackDisconnect(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
335 SMTPTransport
*This
= (SMTPTransport
*)iface
;
336 SMTPRESPONSE response
;
343 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
346 /* FIXME: handle error */
350 if (FAILED(response
.rIxpResult
.hrServerError
))
352 ERR("server error: %s\n", debugstr_a(pBuffer
));
353 /* FIXME: handle error */
357 InternetTransport_DropConnection(&This
->InetTransport
);
360 static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
362 SMTPTransport
*This
= (SMTPTransport
*)iface
;
363 SMTPRESPONSE response
= { 0 };
368 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
371 /* FIXME: handle error */
375 if (FAILED(response
.rIxpResult
.hrServerError
))
377 ERR("server error: %s\n", debugstr_a(pBuffer
));
378 /* FIXME: handle error */
382 response
.command
= SMTP_SEND_MESSAGE
;
383 response
.rIxpResult
.hrResult
= S_OK
;
384 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
387 static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
389 SMTPTransport
*This
= (SMTPTransport
*)iface
;
390 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageProcessResponse
);
393 static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
395 SMTPTransport
*This
= (SMTPTransport
*)iface
;
397 IStream_Release(This
->pending_message
.pstmMsg
);
398 InternetTransport_DoCommand(&This
->InetTransport
, "\n.\n",
399 SMTPTransport_CallbackMessageReadResponse
);
402 static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
404 SMTPTransport
*This
= (SMTPTransport
*)iface
;
405 SMTPRESPONSE response
;
412 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
415 /* FIXME: handle error */
419 if (FAILED(response
.rIxpResult
.hrServerError
))
421 ERR("server error: %s\n", debugstr_a(pBuffer
));
422 /* FIXME: handle error */
426 pszBuffer
= HeapAlloc(GetProcessHeap(), 0, This
->pending_message
.cbSize
);
427 hr
= IStream_Read(This
->pending_message
.pstmMsg
, pszBuffer
, This
->pending_message
.cbSize
, NULL
);
430 /* FIXME: handle error */
433 cbSize
= This
->pending_message
.cbSize
;
435 /* FIXME: map "\n.\n" to "\n..\n", reallocate memory, update cbSize */
437 /* FIXME: properly stream the message rather than writing it all at once */
439 hr
= InternetTransport_Write(&This
->InetTransport
, pszBuffer
, cbSize
,
440 SMTPTransport_CallbackMessageSendDOT
);
442 HeapFree(GetProcessHeap(), 0, pszBuffer
);
445 static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
447 SMTPTransport
*This
= (SMTPTransport
*)iface
;
450 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendDataStream
);
453 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
);
455 static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
457 SMTPTransport
*This
= (SMTPTransport
*)iface
;
460 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
463 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
465 SMTPTransport
*This
= (SMTPTransport
*)iface
;
466 SMTPRESPONSE response
;
471 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
474 /* FIXME: handle error */
478 if (FAILED(response
.rIxpResult
.hrServerError
))
480 ERR("server error: %s\n", debugstr_a(pBuffer
));
481 /* FIXME: handle error */
485 for (; This
->ulCurrentAddressIndex
< This
->pending_message
.rAddressList
.cAddress
; This
->ulCurrentAddressIndex
++)
487 TRACE("address[%d]: %s\n", This
->ulCurrentAddressIndex
,
488 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
490 if ((This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
492 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
494 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ +
495 strlen(This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
497 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
501 sprintf(szCommand
, szCommandFormat
,
502 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
504 This
->ulCurrentAddressIndex
++;
505 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
506 SMTPTransport_CallbackMessageReadToResponse
);
508 HeapFree(GetProcessHeap(), 0, szCommand
);
513 hr
= InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
514 SMTPTransport_CallbackMessageReadDataResponse
);
517 static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
519 SMTPTransport
*This
= (SMTPTransport
*)iface
;
522 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
525 static HRESULT WINAPI
SMTPTransport_QueryInterface(ISMTPTransport2
*iface
, REFIID riid
, void **ppv
)
527 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
529 if (IsEqualIID(riid
, &IID_IUnknown
) ||
530 IsEqualIID(riid
, &IID_IInternetTransport
) ||
531 IsEqualIID(riid
, &IID_ISMTPTransport
) ||
532 IsEqualIID(riid
, &IID_ISMTPTransport2
))
535 ISMTPTransport2_AddRef(iface
);
539 FIXME("no interface for %s\n", debugstr_guid(riid
));
540 return E_NOINTERFACE
;
543 static ULONG WINAPI
SMTPTransport_AddRef(ISMTPTransport2
*iface
)
545 SMTPTransport
*This
= (SMTPTransport
*)iface
;
546 return InterlockedIncrement((LONG
*)&This
->refs
);
549 static ULONG WINAPI
SMTPTransport_Release(ISMTPTransport2
*iface
)
551 SMTPTransport
*This
= (SMTPTransport
*)iface
;
552 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
555 TRACE("destroying %p\n", This
);
556 if (This
->InetTransport
.Status
!= IXP_DISCONNECTED
)
557 InternetTransport_DropConnection(&This
->InetTransport
);
559 if (This
->InetTransport
.pCallback
) ITransportCallback_Release(This
->InetTransport
.pCallback
);
560 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
561 HeapFree(GetProcessHeap(), 0, This
);
566 static HRESULT WINAPI
SMTPTransport_GetServerInfo(ISMTPTransport2
*iface
,
567 LPINETSERVER pInetServer
)
569 SMTPTransport
*This
= (SMTPTransport
*)iface
;
571 TRACE("(%p)\n", pInetServer
);
572 return InternetTransport_GetServerInfo(&This
->InetTransport
, pInetServer
);
575 static IXPTYPE WINAPI
SMTPTransport_GetIXPType(ISMTPTransport2
*iface
)
581 static HRESULT WINAPI
SMTPTransport_IsState(ISMTPTransport2
*iface
,
584 FIXME("(%d): stub\n", isstate
);
588 static HRESULT WINAPI
SMTPTransport_InetServerFromAccount(
589 ISMTPTransport2
*iface
, IImnAccount
*pAccount
, LPINETSERVER pInetServer
)
591 SMTPTransport
*This
= (SMTPTransport
*)iface
;
593 TRACE("(%p, %p)\n", pAccount
, pInetServer
);
594 return InternetTransport_InetServerFromAccount(&This
->InetTransport
, pAccount
, pInetServer
);
597 static HRESULT WINAPI
SMTPTransport_Connect(ISMTPTransport2
*iface
,
598 LPINETSERVER pInetServer
, boolean fAuthenticate
, boolean fCommandLogging
)
600 SMTPTransport
*This
= (SMTPTransport
*)iface
;
603 TRACE("(%p, %s, %s)\n", pInetServer
, fAuthenticate
? "TRUE" : "FALSE", fCommandLogging
? "TRUE" : "FALSE");
605 hr
= InternetTransport_Connect(&This
->InetTransport
, pInetServer
, fAuthenticate
, fCommandLogging
);
609 /* this starts the state machine, which continues in SMTPTransport_CallbackSendHELO */
610 return InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackSendHello
);
613 static HRESULT WINAPI
SMTPTransport_HandsOffCallback(ISMTPTransport2
*iface
)
615 SMTPTransport
*This
= (SMTPTransport
*)iface
;
618 return InternetTransport_HandsOffCallback(&This
->InetTransport
);
621 static HRESULT WINAPI
SMTPTransport_Disconnect(ISMTPTransport2
*iface
)
624 return ISMTPTransport2_CommandQUIT(iface
);
627 static HRESULT WINAPI
SMTPTransport_DropConnection(ISMTPTransport2
*iface
)
629 SMTPTransport
*This
= (SMTPTransport
*)iface
;
632 return InternetTransport_DropConnection(&This
->InetTransport
);
635 static HRESULT WINAPI
SMTPTransport_GetStatus(ISMTPTransport2
*iface
,
636 IXPSTATUS
*pCurrentStatus
)
638 SMTPTransport
*This
= (SMTPTransport
*)iface
;
641 return InternetTransport_GetStatus(&This
->InetTransport
, pCurrentStatus
);
644 static HRESULT WINAPI
SMTPTransport_InitNew(ISMTPTransport2
*iface
,
645 LPSTR pszLogFilePath
, ISMTPCallback
*pCallback
)
647 SMTPTransport
*This
= (SMTPTransport
*)iface
;
649 TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath
), pCallback
);
655 FIXME("not using log file of %s, use Wine debug logging instead\n",
656 debugstr_a(pszLogFilePath
));
658 ISMTPCallback_AddRef(pCallback
);
659 This
->InetTransport
.pCallback
= (ITransportCallback
*)pCallback
;
660 This
->InetTransport
.fInitialised
= TRUE
;
665 static HRESULT WINAPI
SMTPTransport_SendMessage(ISMTPTransport2
*iface
,
666 LPSMTPMESSAGE pMessage
)
668 SMTPTransport
*This
= (SMTPTransport
*)iface
;
670 LPSTR pszFromAddress
= NULL
;
671 const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
676 TRACE("(%p)\n", pMessage
);
678 This
->pending_message
= *pMessage
;
679 IStream_AddRef(pMessage
->pstmMsg
);
681 size
= pMessage
->rAddressList
.cAddress
* sizeof(INETADDR
);
682 This
->addrlist
= HeapAlloc(GetProcessHeap(), 0, size
);
684 return E_OUTOFMEMORY
;
686 memcpy(This
->addrlist
, pMessage
->rAddressList
.prgAddress
, size
);
687 This
->pending_message
.rAddressList
.prgAddress
= This
->addrlist
;
688 This
->ulCurrentAddressIndex
= 0;
690 for (i
= 0; i
< pMessage
->rAddressList
.cAddress
; i
++)
692 if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_FROM
)
694 TRACE("address[%d]: ADDR_FROM, %s\n", i
,
695 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
696 pszFromAddress
= pMessage
->rAddressList
.prgAddress
[i
].szEmail
;
698 else if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
700 TRACE("address[%d]: ADDR_TO, %s\n", i
,
701 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
707 SMTPRESPONSE response
;
708 memset(&response
, 0, sizeof(response
));
709 response
.command
= SMTP_SEND_MESSAGE
;
710 response
.fDone
= TRUE
;
711 response
.pTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
712 response
.rIxpResult
.hrResult
= IXP_E_SMTP_NO_SENDER
;
713 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
716 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszFromAddress
);
718 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
720 return E_OUTOFMEMORY
;
722 sprintf(szCommand
, szCommandFormat
, pszFromAddress
);
724 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
725 SMTPTransport_CallbackMessageReadFromResponse
);
730 static HRESULT WINAPI
SMTPTransport_CommandMAIL(ISMTPTransport2
*iface
, LPSTR pszEmailFrom
)
732 SMTPTransport
*This
= (SMTPTransport
*)iface
;
733 const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
738 TRACE("(%s)\n", debugstr_a(pszEmailFrom
));
743 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailFrom
);
744 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
746 return E_OUTOFMEMORY
;
748 sprintf(szCommand
, szCommandFormat
, pszEmailFrom
);
750 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
751 SMTPTransport_CallbackReadMAILResponse
);
753 HeapFree(GetProcessHeap(), 0, szCommand
);
757 static HRESULT WINAPI
SMTPTransport_CommandRCPT(ISMTPTransport2
*iface
, LPSTR pszEmailTo
)
759 SMTPTransport
*This
= (SMTPTransport
*)iface
;
760 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
765 TRACE("(%s)\n", debugstr_a(pszEmailTo
));
770 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailTo
);
771 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
773 return E_OUTOFMEMORY
;
775 sprintf(szCommand
, szCommandFormat
, pszEmailTo
);
777 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
778 SMTPTransport_CallbackReadRCPTResponse
);
780 HeapFree(GetProcessHeap(), 0, szCommand
);
784 static HRESULT WINAPI
SMTPTransport_CommandEHLO(ISMTPTransport2
*iface
)
786 SMTPTransport
*This
= (SMTPTransport
*)iface
;
787 const char szCommandFormat
[] = "EHLO %s\n";
788 const char szHostname
[] = "localhost"; /* FIXME */
790 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
795 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
797 return E_OUTOFMEMORY
;
799 sprintf(szCommand
, szCommandFormat
, szHostname
);
801 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
802 SMTPTransport_CallbackReadResponseDoNothing
);
804 HeapFree(GetProcessHeap(), 0, szCommand
);
808 static HRESULT WINAPI
SMTPTransport_CommandHELO(ISMTPTransport2
*iface
)
810 SMTPTransport
*This
= (SMTPTransport
*)iface
;
811 const char szCommandFormat
[] = "HELO %s\n";
812 const char szHostname
[] = "localhost"; /* FIXME */
814 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
819 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
821 return E_OUTOFMEMORY
;
823 sprintf(szCommand
, szCommandFormat
, szHostname
);
825 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
826 SMTPTransport_CallbackReadResponseDoNothing
);
828 HeapFree(GetProcessHeap(), 0, szCommand
);
832 static HRESULT WINAPI
SMTPTransport_CommandAUTH(ISMTPTransport2
*iface
,
835 SMTPTransport
*This
= (SMTPTransport
*)iface
;
836 const char szCommandFormat
[] = "AUTH %s\n";
841 TRACE("(%s)\n", debugstr_a(pszAuthType
));
846 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszAuthType
);
847 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
849 return E_OUTOFMEMORY
;
851 sprintf(szCommand
, szCommandFormat
, pszAuthType
);
853 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
854 SMTPTransport_CallbackReadResponseDoNothing
);
856 HeapFree(GetProcessHeap(), 0, szCommand
);
860 static HRESULT WINAPI
SMTPTransport_CommandQUIT(ISMTPTransport2
*iface
)
862 SMTPTransport
*This
= (SMTPTransport
*)iface
;
866 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_DISCONNECTING
);
867 return InternetTransport_DoCommand(&This
->InetTransport
, "QUIT\n",
868 SMTPTransport_CallbackDisconnect
);
871 static HRESULT WINAPI
SMTPTransport_CommandRSET(ISMTPTransport2
*iface
)
873 SMTPTransport
*This
= (SMTPTransport
*)iface
;
877 return InternetTransport_DoCommand(&This
->InetTransport
, "RSET\n",
878 SMTPTransport_CallbackReadResponseDoNothing
);
881 static HRESULT WINAPI
SMTPTransport_CommandDATA(ISMTPTransport2
*iface
)
883 SMTPTransport
*This
= (SMTPTransport
*)iface
;
887 return InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
888 SMTPTransport_CallbackReadDATAResponse
);
891 static HRESULT WINAPI
SMTPTransport_CommandDOT(ISMTPTransport2
*iface
)
897 static HRESULT WINAPI
SMTPTransport_SendDataStream(ISMTPTransport2
*iface
,
898 IStream
*pStream
, ULONG cbSize
)
900 FIXME("(%p, %d)\n", pStream
, cbSize
);
904 static HRESULT WINAPI
SMTPTransport_SetWindow(ISMTPTransport2
*iface
)
910 static HRESULT WINAPI
SMTPTransport_ResetWindow(ISMTPTransport2
*iface
)
916 static HRESULT WINAPI
SMTPTransport_SendMessage2(ISMTPTransport2
*iface
, LPSMTPMESSAGE2 pMessage
)
918 FIXME("(%p)\n", pMessage
);
922 static HRESULT WINAPI
SMTPTransport_CommandRCPT2(ISMTPTransport2
*iface
, LPSTR pszEmailTo
,
925 FIXME("(%s, %u)\n", pszEmailTo
, atDSN
);
929 static const ISMTPTransport2Vtbl SMTPTransport2Vtbl
=
931 SMTPTransport_QueryInterface
,
932 SMTPTransport_AddRef
,
933 SMTPTransport_Release
,
934 SMTPTransport_GetServerInfo
,
935 SMTPTransport_GetIXPType
,
936 SMTPTransport_IsState
,
937 SMTPTransport_InetServerFromAccount
,
938 SMTPTransport_Connect
,
939 SMTPTransport_HandsOffCallback
,
940 SMTPTransport_Disconnect
,
941 SMTPTransport_DropConnection
,
942 SMTPTransport_GetStatus
,
943 SMTPTransport_InitNew
,
944 SMTPTransport_SendMessage
,
945 SMTPTransport_CommandMAIL
,
946 SMTPTransport_CommandRCPT
,
947 SMTPTransport_CommandEHLO
,
948 SMTPTransport_CommandHELO
,
949 SMTPTransport_CommandAUTH
,
950 SMTPTransport_CommandQUIT
,
951 SMTPTransport_CommandRSET
,
952 SMTPTransport_CommandDATA
,
953 SMTPTransport_CommandDOT
,
954 SMTPTransport_SendDataStream
,
955 SMTPTransport_SetWindow
,
956 SMTPTransport_ResetWindow
,
957 SMTPTransport_SendMessage2
,
958 SMTPTransport_CommandRCPT2
961 HRESULT WINAPI
CreateSMTPTransport(ISMTPTransport
**ppTransport
)
964 SMTPTransport
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
966 return E_OUTOFMEMORY
;
968 This
->InetTransport
.u
.vtblSMTP2
= &SMTPTransport2Vtbl
;
970 This
->fESMTP
= FALSE
;
971 hr
= InternetTransport_Init(&This
->InetTransport
);
974 HeapFree(GetProcessHeap(), 0, This
);
978 *ppTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
979 ISMTPTransport_AddRef(*ppTransport
);
985 static HRESULT WINAPI
SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface
,
986 REFIID riid
, LPVOID
*ppv
)
989 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
992 IClassFactory_AddRef(iface
);
995 return E_NOINTERFACE
;
998 static ULONG WINAPI
SMTPTransportCF_AddRef(LPCLASSFACTORY iface
)
1000 return 2; /* non-heap based object */
1003 static ULONG WINAPI
SMTPTransportCF_Release(LPCLASSFACTORY iface
)
1005 return 1; /* non-heap based object */
1008 static HRESULT WINAPI
SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface
,
1009 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
1012 ISMTPTransport
*pSmtpTransport
;
1014 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
1019 return CLASS_E_NOAGGREGATION
;
1021 hr
= CreateSMTPTransport(&pSmtpTransport
);
1025 hr
= ISMTPTransport_QueryInterface(pSmtpTransport
, riid
, ppv
);
1026 ISMTPTransport_Release(pSmtpTransport
);
1031 static HRESULT WINAPI
SMTPTransportCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
1033 FIXME("(%d)\n",fLock
);
1037 static const IClassFactoryVtbl SMTPTransportCFVtbl
=
1039 SMTPTransportCF_QueryInterface
,
1040 SMTPTransportCF_AddRef
,
1041 SMTPTransportCF_Release
,
1042 SMTPTransportCF_CreateInstance
,
1043 SMTPTransportCF_LockServer
1045 static const IClassFactoryVtbl
*SMTPTransportCF
= &SMTPTransportCFVtbl
;
1047 HRESULT
SMTPTransportCF_Create(REFIID riid
, LPVOID
*ppv
)
1049 return IClassFactory_QueryInterface((IClassFactory
*)&SMTPTransportCF
, riid
, ppv
);