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 pResponse
->fDone
= (*pszResponse
!= '-');
64 switch (pResponse
->rIxpResult
.uiServerError
)
66 case 211: hrServerError
= IXP_E_SMTP_211_SYSTEM_STATUS
; break;
67 case 214: hrServerError
= IXP_E_SMTP_214_HELP_MESSAGE
; break;
68 case 220: hrServerError
= IXP_E_SMTP_220_READY
; break;
69 case 221: hrServerError
= IXP_E_SMTP_221_CLOSING
; break;
70 case 245: hrServerError
= IXP_E_SMTP_245_AUTH_SUCCESS
; break;
71 case 250: hrServerError
= IXP_E_SMTP_250_MAIL_ACTION_OKAY
; break;
72 case 251: hrServerError
= IXP_E_SMTP_251_FORWARDING_MAIL
; break;
73 case 334: hrServerError
= IXP_E_SMTP_334_AUTH_READY_RESPONSE
; break;
74 case 354: hrServerError
= IXP_E_SMTP_354_START_MAIL_INPUT
; break;
75 case 421: hrServerError
= IXP_E_SMTP_421_NOT_AVAILABLE
; break;
76 case 450: hrServerError
= IXP_E_SMTP_450_MAILBOX_BUSY
; break;
77 case 451: hrServerError
= IXP_E_SMTP_451_ERROR_PROCESSING
; break;
78 case 452: hrServerError
= IXP_E_SMTP_452_NO_SYSTEM_STORAGE
; break;
79 case 454: hrServerError
= IXP_E_SMTP_454_STARTTLS_FAILED
; break;
80 case 500: hrServerError
= IXP_E_SMTP_500_SYNTAX_ERROR
; break;
81 case 501: hrServerError
= IXP_E_SMTP_501_PARAM_SYNTAX
; break;
82 case 502: hrServerError
= IXP_E_SMTP_502_COMMAND_NOTIMPL
; break;
83 case 503: hrServerError
= IXP_E_SMTP_503_COMMAND_SEQ
; break;
84 case 504: hrServerError
= IXP_E_SMTP_504_COMMAND_PARAM_NOTIMPL
; break;
85 case 530: hrServerError
= IXP_E_SMTP_530_STARTTLS_REQUIRED
; break;
86 case 550: hrServerError
= IXP_E_SMTP_550_MAILBOX_NOT_FOUND
; break;
87 case 551: hrServerError
= IXP_E_SMTP_551_USER_NOT_LOCAL
; break;
88 case 552: hrServerError
= IXP_E_SMTP_552_STORAGE_OVERFLOW
; break;
89 case 553: hrServerError
= IXP_E_SMTP_553_MAILBOX_NAME_SYNTAX
; break;
90 case 554: hrServerError
= IXP_E_SMTP_554_TRANSACT_FAILED
; break;
92 hrServerError
= IXP_E_SMTP_RESPONSE_ERROR
;
95 pResponse
->rIxpResult
.hrResult
= hrServerError
;
96 pResponse
->rIxpResult
.hrServerError
= hrServerError
;
98 if (This
->InetTransport
.pCallback
&& This
->InetTransport
.fCommandLogging
)
100 ITransportCallback_OnCommand(This
->InetTransport
.pCallback
, CMD_RESP
,
101 pResponse
->rIxpResult
.pszResponse
, hrServerError
,
102 (IInternetTransport
*)&This
->InetTransport
.u
.vtbl
);
107 static void SMTPTransport_CallbackDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
112 static void SMTPTransport_CallbackReadResponseDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
114 SMTPTransport
*This
= (SMTPTransport
*)iface
;
117 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackDoNothing
);
120 static void SMTPTransport_CallbackProcessDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
122 SMTPTransport
*This
= (SMTPTransport
*)iface
;
123 SMTPRESPONSE response
= { 0 };
128 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
131 /* FIXME: handle error */
135 response
.command
= SMTP_DATA
;
136 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
138 if (FAILED(response
.rIxpResult
.hrServerError
))
140 ERR("server error: %s\n", debugstr_a(pBuffer
));
141 /* FIXME: handle error */
146 static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
148 SMTPTransport
*This
= (SMTPTransport
*)iface
;
151 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessDATAResponse
);
154 static void SMTPTransport_CallbackProcessMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
156 SMTPTransport
*This
= (SMTPTransport
*)iface
;
157 SMTPRESPONSE response
= { 0 };
162 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
165 /* FIXME: handle error */
169 response
.command
= SMTP_MAIL
;
170 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
172 if (FAILED(response
.rIxpResult
.hrServerError
))
174 ERR("server error: %s\n", debugstr_a(pBuffer
));
175 /* FIXME: handle error */
180 static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
182 SMTPTransport
*This
= (SMTPTransport
*)iface
;
185 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessMAILResponse
);
188 static void SMTPTransport_CallbackProcessRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
190 SMTPTransport
*This
= (SMTPTransport
*)iface
;
191 SMTPRESPONSE response
= { 0 };
196 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
197 This
->addrlist
= NULL
;
199 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
202 /* FIXME: handle error */
206 response
.command
= SMTP_RCPT
;
207 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
209 if (FAILED(response
.rIxpResult
.hrServerError
))
211 ERR("server error: %s\n", debugstr_a(pBuffer
));
212 /* FIXME: handle error */
217 static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
219 SMTPTransport
*This
= (SMTPTransport
*)iface
;
222 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessRCPTResponse
);
225 static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
227 SMTPTransport
*This
= (SMTPTransport
*)iface
;
228 SMTPRESPONSE response
= { 0 };
233 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
236 /* FIXME: handle error */
240 response
.command
= This
->fESMTP
? SMTP_EHLO
: SMTP_HELO
;
241 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
243 if (FAILED(response
.rIxpResult
.hrServerError
))
245 ERR("server error: %s\n", debugstr_a(pBuffer
));
246 /* FIXME: handle error */
252 InternetTransport_ReadLine(&This
->InetTransport
,
253 SMTPTransport_CallbackProcessHelloResp
);
257 /* FIXME: try to authorize */
259 /* always changed to this status, even if authorization not support on server */
260 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_AUTHORIZED
);
261 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_CONNECTED
);
263 memset(&response
, 0, sizeof(response
));
264 response
.command
= SMTP_CONNECTED
;
265 response
.fDone
= TRUE
;
266 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
269 static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
271 SMTPTransport
*This
= (SMTPTransport
*)iface
;
274 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessHelloResp
);
277 static void SMTPTransport_CallbackSendHello(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
279 SMTPTransport
*This
= (SMTPTransport
*)iface
;
280 SMTPRESPONSE response
= { 0 };
282 const char *pszHello
;
284 static const char szHostName
[] = "localhost"; /* FIXME */
288 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
291 /* FIXME: handle error */
295 response
.command
= SMTP_BANNER
;
296 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
298 if (FAILED(response
.rIxpResult
.hrServerError
))
300 ERR("server error: %s\n", debugstr_a(pBuffer
));
301 /* FIXME: handle error */
305 TRACE("(%s)\n", pBuffer
);
307 This
->fESMTP
= strstr(response
.rIxpResult
.pszResponse
, "ESMTP") &&
308 This
->InetTransport
.ServerInfo
.dwFlags
& (ISF_SSLONSAMEPORT
|ISF_QUERYDSNSUPPORT
|ISF_QUERYAUTHSUPPORT
);
315 pszCommand
= HeapAlloc(GetProcessHeap(), 0, strlen(pszHello
) + strlen(szHostName
) + 2);
316 strcpy(pszCommand
, pszHello
);
317 strcat(pszCommand
, szHostName
);
318 pszCommand
[strlen(pszCommand
)+1] = '\0';
319 pszCommand
[strlen(pszCommand
)] = '\n';
321 InternetTransport_DoCommand(&This
->InetTransport
, pszCommand
,
322 SMTPTransport_CallbackRecvHelloResp
);
324 HeapFree(GetProcessHeap(), 0, pszCommand
);
327 static void SMTPTransport_CallbackDisconnect(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
329 SMTPTransport
*This
= (SMTPTransport
*)iface
;
330 SMTPRESPONSE response
;
337 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
340 /* FIXME: handle error */
344 if (FAILED(response
.rIxpResult
.hrServerError
))
346 ERR("server error: %s\n", debugstr_a(pBuffer
));
347 /* FIXME: handle error */
351 InternetTransport_DropConnection(&This
->InetTransport
);
354 static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
356 SMTPTransport
*This
= (SMTPTransport
*)iface
;
357 SMTPRESPONSE response
= { 0 };
362 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
365 /* FIXME: handle error */
369 if (FAILED(response
.rIxpResult
.hrServerError
))
371 ERR("server error: %s\n", debugstr_a(pBuffer
));
372 /* FIXME: handle error */
376 response
.command
= SMTP_SEND_MESSAGE
;
377 response
.rIxpResult
.hrResult
= S_OK
;
378 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
381 static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
383 SMTPTransport
*This
= (SMTPTransport
*)iface
;
384 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageProcessResponse
);
387 static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
389 SMTPTransport
*This
= (SMTPTransport
*)iface
;
391 IStream_Release(This
->pending_message
.pstmMsg
);
392 InternetTransport_DoCommand(&This
->InetTransport
, "\n.\n",
393 SMTPTransport_CallbackMessageReadResponse
);
396 static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
398 SMTPTransport
*This
= (SMTPTransport
*)iface
;
399 SMTPRESPONSE response
;
406 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
409 /* FIXME: handle error */
413 if (FAILED(response
.rIxpResult
.hrServerError
))
415 ERR("server error: %s\n", debugstr_a(pBuffer
));
416 /* FIXME: handle error */
420 pszBuffer
= HeapAlloc(GetProcessHeap(), 0, This
->pending_message
.cbSize
);
421 hr
= IStream_Read(This
->pending_message
.pstmMsg
, pszBuffer
, This
->pending_message
.cbSize
, NULL
);
424 /* FIXME: handle error */
427 cbSize
= This
->pending_message
.cbSize
;
429 /* FIXME: map "\n.\n" to "\n..\n", reallocate memory, update cbSize */
431 /* FIXME: properly stream the message rather than writing it all at once */
433 hr
= InternetTransport_Write(&This
->InetTransport
, pszBuffer
, cbSize
,
434 SMTPTransport_CallbackMessageSendDOT
);
436 HeapFree(GetProcessHeap(), 0, pszBuffer
);
439 static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
441 SMTPTransport
*This
= (SMTPTransport
*)iface
;
444 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendDataStream
);
447 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
);
449 static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
451 SMTPTransport
*This
= (SMTPTransport
*)iface
;
454 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
457 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
459 SMTPTransport
*This
= (SMTPTransport
*)iface
;
460 SMTPRESPONSE response
;
465 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
468 /* FIXME: handle error */
472 if (FAILED(response
.rIxpResult
.hrServerError
))
474 ERR("server error: %s\n", debugstr_a(pBuffer
));
475 /* FIXME: handle error */
479 for (; This
->ulCurrentAddressIndex
< This
->pending_message
.rAddressList
.cAddress
; This
->ulCurrentAddressIndex
++)
481 TRACE("address[%d]: %s\n", This
->ulCurrentAddressIndex
,
482 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
484 if ((This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
486 static const char szCommandFormat
[] = "RCPT TO: <%s>\n";
488 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ +
489 strlen(This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
491 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
495 sprintf(szCommand
, szCommandFormat
,
496 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
498 This
->ulCurrentAddressIndex
++;
499 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
500 SMTPTransport_CallbackMessageReadToResponse
);
502 HeapFree(GetProcessHeap(), 0, szCommand
);
507 hr
= InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
508 SMTPTransport_CallbackMessageReadDataResponse
);
511 static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
513 SMTPTransport
*This
= (SMTPTransport
*)iface
;
516 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
519 static HRESULT WINAPI
SMTPTransport_QueryInterface(ISMTPTransport2
*iface
, REFIID riid
, void **ppv
)
521 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
523 if (IsEqualIID(riid
, &IID_IUnknown
) ||
524 IsEqualIID(riid
, &IID_IInternetTransport
) ||
525 IsEqualIID(riid
, &IID_ISMTPTransport
) ||
526 IsEqualIID(riid
, &IID_ISMTPTransport2
))
529 ISMTPTransport2_AddRef(iface
);
533 FIXME("no interface for %s\n", debugstr_guid(riid
));
534 return E_NOINTERFACE
;
537 static ULONG WINAPI
SMTPTransport_AddRef(ISMTPTransport2
*iface
)
539 SMTPTransport
*This
= (SMTPTransport
*)iface
;
540 return InterlockedIncrement((LONG
*)&This
->refs
);
543 static ULONG WINAPI
SMTPTransport_Release(ISMTPTransport2
*iface
)
545 SMTPTransport
*This
= (SMTPTransport
*)iface
;
546 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
549 TRACE("destroying %p\n", This
);
550 if (This
->InetTransport
.Status
!= IXP_DISCONNECTED
)
551 InternetTransport_DropConnection(&This
->InetTransport
);
553 if (This
->InetTransport
.pCallback
) ITransportCallback_Release(This
->InetTransport
.pCallback
);
554 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
555 HeapFree(GetProcessHeap(), 0, This
);
560 static HRESULT WINAPI
SMTPTransport_GetServerInfo(ISMTPTransport2
*iface
,
561 LPINETSERVER pInetServer
)
563 SMTPTransport
*This
= (SMTPTransport
*)iface
;
565 TRACE("(%p)\n", pInetServer
);
566 return InternetTransport_GetServerInfo(&This
->InetTransport
, pInetServer
);
569 static IXPTYPE WINAPI
SMTPTransport_GetIXPType(ISMTPTransport2
*iface
)
575 static HRESULT WINAPI
SMTPTransport_IsState(ISMTPTransport2
*iface
,
578 FIXME("(%d): stub\n", isstate
);
582 static HRESULT WINAPI
SMTPTransport_InetServerFromAccount(
583 ISMTPTransport2
*iface
, IImnAccount
*pAccount
, LPINETSERVER pInetServer
)
585 SMTPTransport
*This
= (SMTPTransport
*)iface
;
587 TRACE("(%p, %p)\n", pAccount
, pInetServer
);
588 return InternetTransport_InetServerFromAccount(&This
->InetTransport
, pAccount
, pInetServer
);
591 static HRESULT WINAPI
SMTPTransport_Connect(ISMTPTransport2
*iface
,
592 LPINETSERVER pInetServer
, boolean fAuthenticate
, boolean fCommandLogging
)
594 SMTPTransport
*This
= (SMTPTransport
*)iface
;
597 TRACE("(%p, %s, %s)\n", pInetServer
, fAuthenticate
? "TRUE" : "FALSE", fCommandLogging
? "TRUE" : "FALSE");
599 hr
= InternetTransport_Connect(&This
->InetTransport
, pInetServer
, fAuthenticate
, fCommandLogging
);
603 /* this starts the state machine, which continues in SMTPTransport_CallbackSendHELO */
604 return InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackSendHello
);
607 static HRESULT WINAPI
SMTPTransport_HandsOffCallback(ISMTPTransport2
*iface
)
609 SMTPTransport
*This
= (SMTPTransport
*)iface
;
612 return InternetTransport_HandsOffCallback(&This
->InetTransport
);
615 static HRESULT WINAPI
SMTPTransport_Disconnect(ISMTPTransport2
*iface
)
618 return ISMTPTransport2_CommandQUIT(iface
);
621 static HRESULT WINAPI
SMTPTransport_DropConnection(ISMTPTransport2
*iface
)
623 SMTPTransport
*This
= (SMTPTransport
*)iface
;
626 return InternetTransport_DropConnection(&This
->InetTransport
);
629 static HRESULT WINAPI
SMTPTransport_GetStatus(ISMTPTransport2
*iface
,
630 IXPSTATUS
*pCurrentStatus
)
632 SMTPTransport
*This
= (SMTPTransport
*)iface
;
635 return InternetTransport_GetStatus(&This
->InetTransport
, pCurrentStatus
);
638 static HRESULT WINAPI
SMTPTransport_InitNew(ISMTPTransport2
*iface
,
639 LPSTR pszLogFilePath
, ISMTPCallback
*pCallback
)
641 SMTPTransport
*This
= (SMTPTransport
*)iface
;
643 TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath
), pCallback
);
649 FIXME("not using log file of %s, use Wine debug logging instead\n",
650 debugstr_a(pszLogFilePath
));
652 ISMTPCallback_AddRef(pCallback
);
653 This
->InetTransport
.pCallback
= (ITransportCallback
*)pCallback
;
654 This
->InetTransport
.fInitialised
= TRUE
;
659 static HRESULT WINAPI
SMTPTransport_SendMessage(ISMTPTransport2
*iface
,
660 LPSMTPMESSAGE pMessage
)
662 static const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
663 SMTPTransport
*This
= (SMTPTransport
*)iface
;
665 LPSTR pszFromAddress
= NULL
;
670 TRACE("(%p)\n", pMessage
);
672 This
->pending_message
= *pMessage
;
673 IStream_AddRef(pMessage
->pstmMsg
);
675 size
= pMessage
->rAddressList
.cAddress
* sizeof(INETADDR
);
676 This
->addrlist
= HeapAlloc(GetProcessHeap(), 0, size
);
678 return E_OUTOFMEMORY
;
680 memcpy(This
->addrlist
, pMessage
->rAddressList
.prgAddress
, size
);
681 This
->pending_message
.rAddressList
.prgAddress
= This
->addrlist
;
682 This
->ulCurrentAddressIndex
= 0;
684 for (i
= 0; i
< pMessage
->rAddressList
.cAddress
; i
++)
686 if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_FROM
)
688 TRACE("address[%d]: ADDR_FROM, %s\n", i
,
689 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
690 pszFromAddress
= pMessage
->rAddressList
.prgAddress
[i
].szEmail
;
692 else if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
694 TRACE("address[%d]: ADDR_TO, %s\n", i
,
695 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
701 SMTPRESPONSE response
;
702 memset(&response
, 0, sizeof(response
));
703 response
.command
= SMTP_SEND_MESSAGE
;
704 response
.fDone
= TRUE
;
705 response
.pTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
706 response
.rIxpResult
.hrResult
= IXP_E_SMTP_NO_SENDER
;
707 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
710 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszFromAddress
);
712 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
714 return E_OUTOFMEMORY
;
716 sprintf(szCommand
, szCommandFormat
, pszFromAddress
);
718 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
719 SMTPTransport_CallbackMessageReadFromResponse
);
724 static HRESULT WINAPI
SMTPTransport_CommandMAIL(ISMTPTransport2
*iface
, LPSTR pszEmailFrom
)
726 static const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
727 SMTPTransport
*This
= (SMTPTransport
*)iface
;
732 TRACE("(%s)\n", debugstr_a(pszEmailFrom
));
737 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailFrom
);
738 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
740 return E_OUTOFMEMORY
;
742 sprintf(szCommand
, szCommandFormat
, pszEmailFrom
);
744 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
745 SMTPTransport_CallbackReadMAILResponse
);
747 HeapFree(GetProcessHeap(), 0, szCommand
);
751 static HRESULT WINAPI
SMTPTransport_CommandRCPT(ISMTPTransport2
*iface
, LPSTR pszEmailTo
)
753 static const char szCommandFormat
[] = "RCPT TO: <%s>\n";
754 SMTPTransport
*This
= (SMTPTransport
*)iface
;
759 TRACE("(%s)\n", debugstr_a(pszEmailTo
));
764 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailTo
);
765 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
767 return E_OUTOFMEMORY
;
769 sprintf(szCommand
, szCommandFormat
, pszEmailTo
);
771 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
772 SMTPTransport_CallbackReadRCPTResponse
);
774 HeapFree(GetProcessHeap(), 0, szCommand
);
778 static HRESULT WINAPI
SMTPTransport_CommandEHLO(ISMTPTransport2
*iface
)
780 static const char szCommandFormat
[] = "EHLO %s\n";
781 static const char szHostname
[] = "localhost"; /* FIXME */
782 SMTPTransport
*This
= (SMTPTransport
*)iface
;
784 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
789 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
791 return E_OUTOFMEMORY
;
793 sprintf(szCommand
, szCommandFormat
, szHostname
);
795 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
796 SMTPTransport_CallbackReadResponseDoNothing
);
798 HeapFree(GetProcessHeap(), 0, szCommand
);
802 static HRESULT WINAPI
SMTPTransport_CommandHELO(ISMTPTransport2
*iface
)
804 static const char szCommandFormat
[] = "HELO %s\n";
805 static const char szHostname
[] = "localhost"; /* FIXME */
806 SMTPTransport
*This
= (SMTPTransport
*)iface
;
808 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
813 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
815 return E_OUTOFMEMORY
;
817 sprintf(szCommand
, szCommandFormat
, szHostname
);
819 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
820 SMTPTransport_CallbackReadResponseDoNothing
);
822 HeapFree(GetProcessHeap(), 0, szCommand
);
826 static HRESULT WINAPI
SMTPTransport_CommandAUTH(ISMTPTransport2
*iface
,
829 static const char szCommandFormat
[] = "AUTH %s\n";
830 SMTPTransport
*This
= (SMTPTransport
*)iface
;
835 TRACE("(%s)\n", debugstr_a(pszAuthType
));
840 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszAuthType
);
841 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
843 return E_OUTOFMEMORY
;
845 sprintf(szCommand
, szCommandFormat
, pszAuthType
);
847 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
848 SMTPTransport_CallbackReadResponseDoNothing
);
850 HeapFree(GetProcessHeap(), 0, szCommand
);
854 static HRESULT WINAPI
SMTPTransport_CommandQUIT(ISMTPTransport2
*iface
)
856 SMTPTransport
*This
= (SMTPTransport
*)iface
;
860 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_DISCONNECTING
);
861 return InternetTransport_DoCommand(&This
->InetTransport
, "QUIT\n",
862 SMTPTransport_CallbackDisconnect
);
865 static HRESULT WINAPI
SMTPTransport_CommandRSET(ISMTPTransport2
*iface
)
867 SMTPTransport
*This
= (SMTPTransport
*)iface
;
871 return InternetTransport_DoCommand(&This
->InetTransport
, "RSET\n",
872 SMTPTransport_CallbackReadResponseDoNothing
);
875 static HRESULT WINAPI
SMTPTransport_CommandDATA(ISMTPTransport2
*iface
)
877 SMTPTransport
*This
= (SMTPTransport
*)iface
;
881 return InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
882 SMTPTransport_CallbackReadDATAResponse
);
885 static HRESULT WINAPI
SMTPTransport_CommandDOT(ISMTPTransport2
*iface
)
891 static HRESULT WINAPI
SMTPTransport_SendDataStream(ISMTPTransport2
*iface
,
892 IStream
*pStream
, ULONG cbSize
)
894 FIXME("(%p, %d)\n", pStream
, cbSize
);
898 static HRESULT WINAPI
SMTPTransport_SetWindow(ISMTPTransport2
*iface
)
904 static HRESULT WINAPI
SMTPTransport_ResetWindow(ISMTPTransport2
*iface
)
910 static HRESULT WINAPI
SMTPTransport_SendMessage2(ISMTPTransport2
*iface
, LPSMTPMESSAGE2 pMessage
)
912 FIXME("(%p)\n", pMessage
);
916 static HRESULT WINAPI
SMTPTransport_CommandRCPT2(ISMTPTransport2
*iface
, LPSTR pszEmailTo
,
919 FIXME("(%s, %u)\n", pszEmailTo
, atDSN
);
923 static const ISMTPTransport2Vtbl SMTPTransport2Vtbl
=
925 SMTPTransport_QueryInterface
,
926 SMTPTransport_AddRef
,
927 SMTPTransport_Release
,
928 SMTPTransport_GetServerInfo
,
929 SMTPTransport_GetIXPType
,
930 SMTPTransport_IsState
,
931 SMTPTransport_InetServerFromAccount
,
932 SMTPTransport_Connect
,
933 SMTPTransport_HandsOffCallback
,
934 SMTPTransport_Disconnect
,
935 SMTPTransport_DropConnection
,
936 SMTPTransport_GetStatus
,
937 SMTPTransport_InitNew
,
938 SMTPTransport_SendMessage
,
939 SMTPTransport_CommandMAIL
,
940 SMTPTransport_CommandRCPT
,
941 SMTPTransport_CommandEHLO
,
942 SMTPTransport_CommandHELO
,
943 SMTPTransport_CommandAUTH
,
944 SMTPTransport_CommandQUIT
,
945 SMTPTransport_CommandRSET
,
946 SMTPTransport_CommandDATA
,
947 SMTPTransport_CommandDOT
,
948 SMTPTransport_SendDataStream
,
949 SMTPTransport_SetWindow
,
950 SMTPTransport_ResetWindow
,
951 SMTPTransport_SendMessage2
,
952 SMTPTransport_CommandRCPT2
955 HRESULT WINAPI
CreateSMTPTransport(ISMTPTransport
**ppTransport
)
958 SMTPTransport
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
960 return E_OUTOFMEMORY
;
962 This
->InetTransport
.u
.vtblSMTP2
= &SMTPTransport2Vtbl
;
964 This
->fESMTP
= FALSE
;
965 hr
= InternetTransport_Init(&This
->InetTransport
);
968 HeapFree(GetProcessHeap(), 0, This
);
972 *ppTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
973 ISMTPTransport_AddRef(*ppTransport
);
979 static HRESULT WINAPI
SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface
,
980 REFIID riid
, LPVOID
*ppv
)
983 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
986 IClassFactory_AddRef(iface
);
989 return E_NOINTERFACE
;
992 static ULONG WINAPI
SMTPTransportCF_AddRef(LPCLASSFACTORY iface
)
994 return 2; /* non-heap based object */
997 static ULONG WINAPI
SMTPTransportCF_Release(LPCLASSFACTORY iface
)
999 return 1; /* non-heap based object */
1002 static HRESULT WINAPI
SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface
,
1003 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
1006 ISMTPTransport
*pSmtpTransport
;
1008 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
1013 return CLASS_E_NOAGGREGATION
;
1015 hr
= CreateSMTPTransport(&pSmtpTransport
);
1019 hr
= ISMTPTransport_QueryInterface(pSmtpTransport
, riid
, ppv
);
1020 ISMTPTransport_Release(pSmtpTransport
);
1025 static HRESULT WINAPI
SMTPTransportCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
1027 FIXME("(%d)\n",fLock
);
1031 static const IClassFactoryVtbl SMTPTransportCFVtbl
=
1033 SMTPTransportCF_QueryInterface
,
1034 SMTPTransportCF_AddRef
,
1035 SMTPTransportCF_Release
,
1036 SMTPTransportCF_CreateInstance
,
1037 SMTPTransportCF_LockServer
1039 static const IClassFactoryVtbl
*SMTPTransportCF
= &SMTPTransportCFVtbl
;
1041 HRESULT
SMTPTransportCF_Create(REFIID riid
, LPVOID
*ppv
)
1043 return IClassFactory_QueryInterface((IClassFactory
*)&SMTPTransportCF
, riid
, ppv
);