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 IUnknown_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";
735 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailFrom
);
738 TRACE("(%s)\n", debugstr_a(pszEmailFrom
));
743 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
745 return E_OUTOFMEMORY
;
747 sprintf(szCommand
, szCommandFormat
, pszEmailFrom
);
749 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
750 SMTPTransport_CallbackReadMAILResponse
);
752 HeapFree(GetProcessHeap(), 0, szCommand
);
756 static HRESULT WINAPI
SMTPTransport_CommandRCPT(ISMTPTransport2
*iface
, LPSTR pszEmailTo
)
758 SMTPTransport
*This
= (SMTPTransport
*)iface
;
759 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
761 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailTo
);
764 TRACE("(%s)\n", debugstr_a(pszEmailTo
));
769 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
771 return E_OUTOFMEMORY
;
773 sprintf(szCommand
, szCommandFormat
, pszEmailTo
);
775 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
776 SMTPTransport_CallbackReadRCPTResponse
);
778 HeapFree(GetProcessHeap(), 0, szCommand
);
782 static HRESULT WINAPI
SMTPTransport_CommandEHLO(ISMTPTransport2
*iface
)
784 SMTPTransport
*This
= (SMTPTransport
*)iface
;
785 const char szCommandFormat
[] = "EHLO %s\n";
786 const char szHostname
[] = "localhost"; /* FIXME */
788 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
793 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
795 return E_OUTOFMEMORY
;
797 sprintf(szCommand
, szCommandFormat
, szHostname
);
799 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
800 SMTPTransport_CallbackReadResponseDoNothing
);
802 HeapFree(GetProcessHeap(), 0, szCommand
);
806 static HRESULT WINAPI
SMTPTransport_CommandHELO(ISMTPTransport2
*iface
)
808 SMTPTransport
*This
= (SMTPTransport
*)iface
;
809 const char szCommandFormat
[] = "HELO %s\n";
810 const char szHostname
[] = "localhost"; /* FIXME */
812 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
817 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
819 return E_OUTOFMEMORY
;
821 sprintf(szCommand
, szCommandFormat
, szHostname
);
823 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
824 SMTPTransport_CallbackReadResponseDoNothing
);
826 HeapFree(GetProcessHeap(), 0, szCommand
);
830 static HRESULT WINAPI
SMTPTransport_CommandAUTH(ISMTPTransport2
*iface
,
833 SMTPTransport
*This
= (SMTPTransport
*)iface
;
834 const char szCommandFormat
[] = "AUTH %s\n";
836 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszAuthType
);
839 TRACE("(%s)\n", debugstr_a(pszAuthType
));
844 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
846 return E_OUTOFMEMORY
;
848 sprintf(szCommand
, szCommandFormat
, pszAuthType
);
850 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
851 SMTPTransport_CallbackReadResponseDoNothing
);
853 HeapFree(GetProcessHeap(), 0, szCommand
);
857 static HRESULT WINAPI
SMTPTransport_CommandQUIT(ISMTPTransport2
*iface
)
859 SMTPTransport
*This
= (SMTPTransport
*)iface
;
863 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_DISCONNECTING
);
864 return InternetTransport_DoCommand(&This
->InetTransport
, "QUIT\n",
865 SMTPTransport_CallbackDisconnect
);
868 static HRESULT WINAPI
SMTPTransport_CommandRSET(ISMTPTransport2
*iface
)
870 SMTPTransport
*This
= (SMTPTransport
*)iface
;
874 return InternetTransport_DoCommand(&This
->InetTransport
, "RSET\n",
875 SMTPTransport_CallbackReadResponseDoNothing
);
878 static HRESULT WINAPI
SMTPTransport_CommandDATA(ISMTPTransport2
*iface
)
880 SMTPTransport
*This
= (SMTPTransport
*)iface
;
884 return InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
885 SMTPTransport_CallbackReadDATAResponse
);
888 static HRESULT WINAPI
SMTPTransport_CommandDOT(ISMTPTransport2
*iface
)
894 static HRESULT WINAPI
SMTPTransport_SendDataStream(ISMTPTransport2
*iface
,
895 IStream
*pStream
, ULONG cbSize
)
897 FIXME("(%p, %d)\n", pStream
, cbSize
);
901 static HRESULT WINAPI
SMTPTransport_SetWindow(ISMTPTransport2
*iface
)
907 static HRESULT WINAPI
SMTPTransport_ResetWindow(ISMTPTransport2
*iface
)
913 static HRESULT WINAPI
SMTPTransport_SendMessage2(ISMTPTransport2
*iface
, LPSMTPMESSAGE2 pMessage
)
915 FIXME("(%p)\n", pMessage
);
919 static HRESULT WINAPI
SMTPTransport_CommandRCPT2(ISMTPTransport2
*iface
, LPSTR pszEmailTo
,
922 FIXME("(%s, %u)\n", pszEmailTo
, atDSN
);
926 static const ISMTPTransport2Vtbl SMTPTransport2Vtbl
=
928 SMTPTransport_QueryInterface
,
929 SMTPTransport_AddRef
,
930 SMTPTransport_Release
,
931 SMTPTransport_GetServerInfo
,
932 SMTPTransport_GetIXPType
,
933 SMTPTransport_IsState
,
934 SMTPTransport_InetServerFromAccount
,
935 SMTPTransport_Connect
,
936 SMTPTransport_HandsOffCallback
,
937 SMTPTransport_Disconnect
,
938 SMTPTransport_DropConnection
,
939 SMTPTransport_GetStatus
,
940 SMTPTransport_InitNew
,
941 SMTPTransport_SendMessage
,
942 SMTPTransport_CommandMAIL
,
943 SMTPTransport_CommandRCPT
,
944 SMTPTransport_CommandEHLO
,
945 SMTPTransport_CommandHELO
,
946 SMTPTransport_CommandAUTH
,
947 SMTPTransport_CommandQUIT
,
948 SMTPTransport_CommandRSET
,
949 SMTPTransport_CommandDATA
,
950 SMTPTransport_CommandDOT
,
951 SMTPTransport_SendDataStream
,
952 SMTPTransport_SetWindow
,
953 SMTPTransport_ResetWindow
,
954 SMTPTransport_SendMessage2
,
955 SMTPTransport_CommandRCPT2
958 HRESULT WINAPI
CreateSMTPTransport(ISMTPTransport
**ppTransport
)
961 SMTPTransport
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
963 return E_OUTOFMEMORY
;
965 This
->InetTransport
.u
.vtblSMTP2
= &SMTPTransport2Vtbl
;
967 This
->fESMTP
= FALSE
;
968 hr
= InternetTransport_Init(&This
->InetTransport
);
971 HeapFree(GetProcessHeap(), 0, This
);
975 *ppTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
976 ISMTPTransport_AddRef(*ppTransport
);
982 static HRESULT WINAPI
SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface
,
983 REFIID riid
, LPVOID
*ppv
)
986 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
989 IUnknown_AddRef(iface
);
992 return E_NOINTERFACE
;
995 static ULONG WINAPI
SMTPTransportCF_AddRef(LPCLASSFACTORY iface
)
997 return 2; /* non-heap based object */
1000 static ULONG WINAPI
SMTPTransportCF_Release(LPCLASSFACTORY iface
)
1002 return 1; /* non-heap based object */
1005 static HRESULT WINAPI
SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface
,
1006 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
1009 ISMTPTransport
*pSmtpTransport
;
1011 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
1016 return CLASS_E_NOAGGREGATION
;
1018 hr
= CreateSMTPTransport(&pSmtpTransport
);
1022 hr
= ISMTPTransport_QueryInterface(pSmtpTransport
, riid
, ppv
);
1023 ISMTPTransport_Release(pSmtpTransport
);
1028 static HRESULT WINAPI
SMTPTransportCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
1030 FIXME("(%d)\n",fLock
);
1034 static const IClassFactoryVtbl SMTPTransportCFVtbl
=
1036 SMTPTransportCF_QueryInterface
,
1037 SMTPTransportCF_AddRef
,
1038 SMTPTransportCF_Release
,
1039 SMTPTransportCF_CreateInstance
,
1040 SMTPTransportCF_LockServer
1042 static const IClassFactoryVtbl
*SMTPTransportCF
= &SMTPTransportCFVtbl
;
1044 HRESULT
SMTPTransportCF_Create(REFIID riid
, LPVOID
*ppv
)
1046 return IClassFactory_QueryInterface((IClassFactory
*)&SMTPTransportCF
, riid
, ppv
);