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 #include "inetcomm_private.h"
27 InternetTransport InetTransport
;
30 SMTPMESSAGE pending_message
;
32 ULONG ulCurrentAddressIndex
;
35 static HRESULT
SMTPTransport_ParseResponse(SMTPTransport
*This
, char *pszResponse
, SMTPRESPONSE
*pResponse
)
37 HRESULT hrServerError
;
39 TRACE("response: %s\n", debugstr_a(pszResponse
));
41 if (!isdigit(*pszResponse
))
42 return IXP_E_SMTP_RESPONSE_ERROR
;
43 pResponse
->pTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
44 pResponse
->rIxpResult
.pszResponse
= pszResponse
;
45 pResponse
->rIxpResult
.dwSocketError
= 0;
46 pResponse
->rIxpResult
.uiServerError
= strtol(pszResponse
, &pszResponse
, 10);
47 if (*pszResponse
== '-')
49 pResponse
->fDone
= FALSE
;
53 pResponse
->fDone
= TRUE
;
55 switch (pResponse
->rIxpResult
.uiServerError
)
57 case 211: hrServerError
= IXP_E_SMTP_211_SYSTEM_STATUS
; break;
58 case 214: hrServerError
= IXP_E_SMTP_214_HELP_MESSAGE
; break;
59 case 220: hrServerError
= IXP_E_SMTP_220_READY
; break;
60 case 221: hrServerError
= IXP_E_SMTP_221_CLOSING
; break;
61 case 245: hrServerError
= IXP_E_SMTP_245_AUTH_SUCCESS
; break;
62 case 250: hrServerError
= IXP_E_SMTP_250_MAIL_ACTION_OKAY
; break;
63 case 251: hrServerError
= IXP_E_SMTP_251_FORWARDING_MAIL
; break;
64 case 334: hrServerError
= IXP_E_SMTP_334_AUTH_READY_RESPONSE
; break;
65 case 354: hrServerError
= IXP_E_SMTP_354_START_MAIL_INPUT
; break;
66 case 421: hrServerError
= IXP_E_SMTP_421_NOT_AVAILABLE
; break;
67 case 450: hrServerError
= IXP_E_SMTP_450_MAILBOX_BUSY
; break;
68 case 451: hrServerError
= IXP_E_SMTP_451_ERROR_PROCESSING
; break;
69 case 452: hrServerError
= IXP_E_SMTP_452_NO_SYSTEM_STORAGE
; break;
70 case 454: hrServerError
= IXP_E_SMTP_454_STARTTLS_FAILED
; break;
71 case 500: hrServerError
= IXP_E_SMTP_500_SYNTAX_ERROR
; break;
72 case 501: hrServerError
= IXP_E_SMTP_501_PARAM_SYNTAX
; break;
73 case 502: hrServerError
= IXP_E_SMTP_502_COMMAND_NOTIMPL
; break;
74 case 503: hrServerError
= IXP_E_SMTP_503_COMMAND_SEQ
; break;
75 case 504: hrServerError
= IXP_E_SMTP_504_COMMAND_PARAM_NOTIMPL
; break;
76 case 530: hrServerError
= IXP_E_SMTP_530_STARTTLS_REQUIRED
; break;
77 case 550: hrServerError
= IXP_E_SMTP_550_MAILBOX_NOT_FOUND
; break;
78 case 551: hrServerError
= IXP_E_SMTP_551_USER_NOT_LOCAL
; break;
79 case 552: hrServerError
= IXP_E_SMTP_552_STORAGE_OVERFLOW
; break;
80 case 553: hrServerError
= IXP_E_SMTP_553_MAILBOX_NAME_SYNTAX
; break;
81 case 554: hrServerError
= IXP_E_SMTP_554_TRANSACT_FAILED
; break;
83 hrServerError
= IXP_E_SMTP_RESPONSE_ERROR
;
86 pResponse
->rIxpResult
.hrResult
= hrServerError
;
87 pResponse
->rIxpResult
.hrServerError
= hrServerError
;
89 if (This
->InetTransport
.pCallback
&& This
->InetTransport
.fCommandLogging
)
91 ITransportCallback_OnCommand(This
->InetTransport
.pCallback
, CMD_RESP
,
92 pResponse
->rIxpResult
.pszResponse
, hrServerError
,
93 (IInternetTransport
*)&This
->InetTransport
.u
.vtbl
);
98 static void SMTPTransport_CallbackDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
103 static void SMTPTransport_CallbackReadResponseDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
105 SMTPTransport
*This
= (SMTPTransport
*)iface
;
108 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackDoNothing
);
111 static void SMTPTransport_CallbackProcessDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
113 SMTPTransport
*This
= (SMTPTransport
*)iface
;
114 SMTPRESPONSE response
= { 0 };
119 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
122 /* FIXME: handle error */
126 response
.command
= SMTP_DATA
;
127 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
129 if (FAILED(response
.rIxpResult
.hrServerError
))
131 ERR("server error: %s\n", debugstr_a(pBuffer
));
132 /* FIXME: handle error */
137 static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
139 SMTPTransport
*This
= (SMTPTransport
*)iface
;
142 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessDATAResponse
);
145 static void SMTPTransport_CallbackProcessMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
147 SMTPTransport
*This
= (SMTPTransport
*)iface
;
148 SMTPRESPONSE response
= { 0 };
153 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
156 /* FIXME: handle error */
160 response
.command
= SMTP_MAIL
;
161 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
163 if (FAILED(response
.rIxpResult
.hrServerError
))
165 ERR("server error: %s\n", debugstr_a(pBuffer
));
166 /* FIXME: handle error */
171 static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
173 SMTPTransport
*This
= (SMTPTransport
*)iface
;
176 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessMAILResponse
);
179 static void SMTPTransport_CallbackProcessRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
181 SMTPTransport
*This
= (SMTPTransport
*)iface
;
182 SMTPRESPONSE response
= { 0 };
187 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
188 This
->addrlist
= NULL
;
190 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
193 /* FIXME: handle error */
197 response
.command
= SMTP_RCPT
;
198 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
200 if (FAILED(response
.rIxpResult
.hrServerError
))
202 ERR("server error: %s\n", debugstr_a(pBuffer
));
203 /* FIXME: handle error */
208 static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
210 SMTPTransport
*This
= (SMTPTransport
*)iface
;
213 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessRCPTResponse
);
216 static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
218 SMTPTransport
*This
= (SMTPTransport
*)iface
;
219 SMTPRESPONSE response
= { 0 };
224 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
227 /* FIXME: handle error */
231 response
.command
= This
->fESMTP
? SMTP_EHLO
: SMTP_HELO
;
232 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
234 if (FAILED(response
.rIxpResult
.hrServerError
))
236 ERR("server error: %s\n", debugstr_a(pBuffer
));
237 /* FIXME: handle error */
243 InternetTransport_ReadLine(&This
->InetTransport
,
244 SMTPTransport_CallbackProcessHelloResp
);
248 /* FIXME: try to authorize */
250 /* always changed to this status, even if authorization not support on server */
251 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_AUTHORIZED
);
252 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_CONNECTED
);
254 memset(&response
, 0, sizeof(response
));
255 response
.command
= SMTP_CONNECTED
;
256 response
.fDone
= TRUE
;
257 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
260 static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
262 SMTPTransport
*This
= (SMTPTransport
*)iface
;
265 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessHelloResp
);
268 static void SMTPTransport_CallbackSendHello(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
270 SMTPTransport
*This
= (SMTPTransport
*)iface
;
271 SMTPRESPONSE response
= { 0 };
273 const char *pszHello
;
275 const char szHostName
[] = "localhost"; /* FIXME */
279 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
282 /* FIXME: handle error */
286 response
.command
= SMTP_BANNER
;
287 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
289 if (FAILED(response
.rIxpResult
.hrServerError
))
291 ERR("server error: %s\n", debugstr_a(pBuffer
));
292 /* FIXME: handle error */
296 TRACE("(%s)\n", pBuffer
);
298 This
->fESMTP
= strstr(response
.rIxpResult
.pszResponse
, "ESMTP") &&
299 This
->InetTransport
.ServerInfo
.dwFlags
& (ISF_SSLONSAMEPORT
|ISF_QUERYDSNSUPPORT
|ISF_QUERYAUTHSUPPORT
);
306 pszCommand
= HeapAlloc(GetProcessHeap(), 0, strlen(pszHello
) + strlen(szHostName
) + 2);
307 strcpy(pszCommand
, pszHello
);
308 strcat(pszCommand
, szHostName
);
309 pszCommand
[strlen(pszCommand
)+1] = '\0';
310 pszCommand
[strlen(pszCommand
)] = '\n';
312 InternetTransport_DoCommand(&This
->InetTransport
, pszCommand
,
313 SMTPTransport_CallbackRecvHelloResp
);
315 HeapFree(GetProcessHeap(), 0, pszCommand
);
318 static void SMTPTransport_CallbackDisconnect(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
320 SMTPTransport
*This
= (SMTPTransport
*)iface
;
321 SMTPRESPONSE response
;
328 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
331 /* FIXME: handle error */
335 if (FAILED(response
.rIxpResult
.hrServerError
))
337 ERR("server error: %s\n", debugstr_a(pBuffer
));
338 /* FIXME: handle error */
342 InternetTransport_DropConnection(&This
->InetTransport
);
345 static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
347 SMTPTransport
*This
= (SMTPTransport
*)iface
;
348 SMTPRESPONSE response
= { 0 };
353 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
356 /* FIXME: handle error */
360 if (FAILED(response
.rIxpResult
.hrServerError
))
362 ERR("server error: %s\n", debugstr_a(pBuffer
));
363 /* FIXME: handle error */
367 response
.command
= SMTP_SEND_MESSAGE
;
368 response
.rIxpResult
.hrResult
= S_OK
;
369 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
372 static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
374 SMTPTransport
*This
= (SMTPTransport
*)iface
;
375 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageProcessResponse
);
378 static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
380 SMTPTransport
*This
= (SMTPTransport
*)iface
;
382 IStream_Release(This
->pending_message
.pstmMsg
);
383 InternetTransport_DoCommand(&This
->InetTransport
, "\n.\n",
384 SMTPTransport_CallbackMessageReadResponse
);
387 static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
389 SMTPTransport
*This
= (SMTPTransport
*)iface
;
390 SMTPRESPONSE response
;
397 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
400 /* FIXME: handle error */
404 if (FAILED(response
.rIxpResult
.hrServerError
))
406 ERR("server error: %s\n", debugstr_a(pBuffer
));
407 /* FIXME: handle error */
411 pszBuffer
= HeapAlloc(GetProcessHeap(), 0, This
->pending_message
.cbSize
);
412 hr
= IStream_Read(This
->pending_message
.pstmMsg
, pszBuffer
, This
->pending_message
.cbSize
, NULL
);
415 /* FIXME: handle error */
418 cbSize
= This
->pending_message
.cbSize
;
420 /* FIXME: map "\n.\n" to "\n..\n", reallocate memory, update cbSize */
422 /* FIXME: properly stream the message rather than writing it all at once */
424 hr
= InternetTransport_Write(&This
->InetTransport
, pszBuffer
, cbSize
,
425 SMTPTransport_CallbackMessageSendDOT
);
427 HeapFree(GetProcessHeap(), 0, pszBuffer
);
430 static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
432 SMTPTransport
*This
= (SMTPTransport
*)iface
;
435 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendDataStream
);
438 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
);
440 static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
442 SMTPTransport
*This
= (SMTPTransport
*)iface
;
445 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
448 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
450 SMTPTransport
*This
= (SMTPTransport
*)iface
;
451 SMTPRESPONSE response
;
456 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
459 /* FIXME: handle error */
463 if (FAILED(response
.rIxpResult
.hrServerError
))
465 ERR("server error: %s\n", debugstr_a(pBuffer
));
466 /* FIXME: handle error */
470 for (; This
->ulCurrentAddressIndex
< This
->pending_message
.rAddressList
.cAddress
; This
->ulCurrentAddressIndex
++)
472 TRACE("address[%d]: %s\n", This
->ulCurrentAddressIndex
,
473 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
475 if ((This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
477 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
479 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ +
480 strlen(This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
482 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
486 sprintf(szCommand
, szCommandFormat
,
487 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
489 This
->ulCurrentAddressIndex
++;
490 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
491 SMTPTransport_CallbackMessageReadToResponse
);
493 HeapFree(GetProcessHeap(), 0, szCommand
);
498 hr
= InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
499 SMTPTransport_CallbackMessageReadDataResponse
);
502 static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
504 SMTPTransport
*This
= (SMTPTransport
*)iface
;
507 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
510 static HRESULT WINAPI
SMTPTransport_QueryInterface(ISMTPTransport2
*iface
, REFIID riid
, void **ppv
)
512 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
514 if (IsEqualIID(riid
, &IID_IUnknown
) ||
515 IsEqualIID(riid
, &IID_IInternetTransport
) ||
516 IsEqualIID(riid
, &IID_ISMTPTransport
) ||
517 IsEqualIID(riid
, &IID_ISMTPTransport2
))
520 ISMTPTransport2_AddRef(iface
);
524 FIXME("no interface for %s\n", debugstr_guid(riid
));
525 return E_NOINTERFACE
;
528 static ULONG WINAPI
SMTPTransport_AddRef(ISMTPTransport2
*iface
)
530 SMTPTransport
*This
= (SMTPTransport
*)iface
;
531 return InterlockedIncrement((LONG
*)&This
->refs
);
534 static ULONG WINAPI
SMTPTransport_Release(ISMTPTransport2
*iface
)
536 SMTPTransport
*This
= (SMTPTransport
*)iface
;
537 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
540 TRACE("destroying %p\n", This
);
541 if (This
->InetTransport
.Status
!= IXP_DISCONNECTED
)
542 InternetTransport_DropConnection(&This
->InetTransport
);
544 if (This
->InetTransport
.pCallback
) ITransportCallback_Release(This
->InetTransport
.pCallback
);
545 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
546 HeapFree(GetProcessHeap(), 0, This
);
551 static HRESULT WINAPI
SMTPTransport_GetServerInfo(ISMTPTransport2
*iface
,
552 LPINETSERVER pInetServer
)
554 SMTPTransport
*This
= (SMTPTransport
*)iface
;
556 TRACE("(%p)\n", pInetServer
);
557 return InternetTransport_GetServerInfo(&This
->InetTransport
, pInetServer
);
560 static IXPTYPE WINAPI
SMTPTransport_GetIXPType(ISMTPTransport2
*iface
)
566 static HRESULT WINAPI
SMTPTransport_IsState(ISMTPTransport2
*iface
,
569 FIXME("(%d): stub\n", isstate
);
573 static HRESULT WINAPI
SMTPTransport_InetServerFromAccount(
574 ISMTPTransport2
*iface
, IImnAccount
*pAccount
, LPINETSERVER pInetServer
)
576 SMTPTransport
*This
= (SMTPTransport
*)iface
;
578 TRACE("(%p, %p)\n", pAccount
, pInetServer
);
579 return InternetTransport_InetServerFromAccount(&This
->InetTransport
, pAccount
, pInetServer
);
582 static HRESULT WINAPI
SMTPTransport_Connect(ISMTPTransport2
*iface
,
583 LPINETSERVER pInetServer
, boolean fAuthenticate
, boolean fCommandLogging
)
585 SMTPTransport
*This
= (SMTPTransport
*)iface
;
588 TRACE("(%p, %s, %s)\n", pInetServer
, fAuthenticate
? "TRUE" : "FALSE", fCommandLogging
? "TRUE" : "FALSE");
590 hr
= InternetTransport_Connect(&This
->InetTransport
, pInetServer
, fAuthenticate
, fCommandLogging
);
594 /* this starts the state machine, which continues in SMTPTransport_CallbackSendHELO */
595 return InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackSendHello
);
598 static HRESULT WINAPI
SMTPTransport_HandsOffCallback(ISMTPTransport2
*iface
)
600 SMTPTransport
*This
= (SMTPTransport
*)iface
;
603 return InternetTransport_HandsOffCallback(&This
->InetTransport
);
606 static HRESULT WINAPI
SMTPTransport_Disconnect(ISMTPTransport2
*iface
)
609 return ISMTPTransport2_CommandQUIT(iface
);
612 static HRESULT WINAPI
SMTPTransport_DropConnection(ISMTPTransport2
*iface
)
614 SMTPTransport
*This
= (SMTPTransport
*)iface
;
617 return InternetTransport_DropConnection(&This
->InetTransport
);
620 static HRESULT WINAPI
SMTPTransport_GetStatus(ISMTPTransport2
*iface
,
621 IXPSTATUS
*pCurrentStatus
)
623 SMTPTransport
*This
= (SMTPTransport
*)iface
;
626 return InternetTransport_GetStatus(&This
->InetTransport
, pCurrentStatus
);
629 static HRESULT WINAPI
SMTPTransport_InitNew(ISMTPTransport2
*iface
,
630 LPSTR pszLogFilePath
, ISMTPCallback
*pCallback
)
632 SMTPTransport
*This
= (SMTPTransport
*)iface
;
634 TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath
), pCallback
);
640 FIXME("not using log file of %s, use Wine debug logging instead\n",
641 debugstr_a(pszLogFilePath
));
643 ISMTPCallback_AddRef(pCallback
);
644 This
->InetTransport
.pCallback
= (ITransportCallback
*)pCallback
;
645 This
->InetTransport
.fInitialised
= TRUE
;
650 static HRESULT WINAPI
SMTPTransport_SendMessage(ISMTPTransport2
*iface
,
651 LPSMTPMESSAGE pMessage
)
653 SMTPTransport
*This
= (SMTPTransport
*)iface
;
655 LPSTR pszFromAddress
= NULL
;
656 const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
661 TRACE("(%p)\n", pMessage
);
663 This
->pending_message
= *pMessage
;
664 IStream_AddRef(pMessage
->pstmMsg
);
666 size
= pMessage
->rAddressList
.cAddress
* sizeof(INETADDR
);
667 This
->addrlist
= HeapAlloc(GetProcessHeap(), 0, size
);
669 return E_OUTOFMEMORY
;
671 memcpy(This
->addrlist
, pMessage
->rAddressList
.prgAddress
, size
);
672 This
->pending_message
.rAddressList
.prgAddress
= This
->addrlist
;
673 This
->ulCurrentAddressIndex
= 0;
675 for (i
= 0; i
< pMessage
->rAddressList
.cAddress
; i
++)
677 if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_FROM
)
679 TRACE("address[%d]: ADDR_FROM, %s\n", i
,
680 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
681 pszFromAddress
= pMessage
->rAddressList
.prgAddress
[i
].szEmail
;
683 else if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
685 TRACE("address[%d]: ADDR_TO, %s\n", i
,
686 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
692 SMTPRESPONSE response
;
693 memset(&response
, 0, sizeof(response
));
694 response
.command
= SMTP_SEND_MESSAGE
;
695 response
.fDone
= TRUE
;
696 response
.pTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
697 response
.rIxpResult
.hrResult
= IXP_E_SMTP_NO_SENDER
;
698 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
701 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszFromAddress
);
703 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
705 return E_OUTOFMEMORY
;
707 sprintf(szCommand
, szCommandFormat
, pszFromAddress
);
709 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
710 SMTPTransport_CallbackMessageReadFromResponse
);
715 static HRESULT WINAPI
SMTPTransport_CommandMAIL(ISMTPTransport2
*iface
, LPSTR pszEmailFrom
)
717 SMTPTransport
*This
= (SMTPTransport
*)iface
;
718 const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
723 TRACE("(%s)\n", debugstr_a(pszEmailFrom
));
728 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailFrom
);
729 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
731 return E_OUTOFMEMORY
;
733 sprintf(szCommand
, szCommandFormat
, pszEmailFrom
);
735 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
736 SMTPTransport_CallbackReadMAILResponse
);
738 HeapFree(GetProcessHeap(), 0, szCommand
);
742 static HRESULT WINAPI
SMTPTransport_CommandRCPT(ISMTPTransport2
*iface
, LPSTR pszEmailTo
)
744 SMTPTransport
*This
= (SMTPTransport
*)iface
;
745 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
750 TRACE("(%s)\n", debugstr_a(pszEmailTo
));
755 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailTo
);
756 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
758 return E_OUTOFMEMORY
;
760 sprintf(szCommand
, szCommandFormat
, pszEmailTo
);
762 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
763 SMTPTransport_CallbackReadRCPTResponse
);
765 HeapFree(GetProcessHeap(), 0, szCommand
);
769 static HRESULT WINAPI
SMTPTransport_CommandEHLO(ISMTPTransport2
*iface
)
771 SMTPTransport
*This
= (SMTPTransport
*)iface
;
772 const char szCommandFormat
[] = "EHLO %s\n";
773 const char szHostname
[] = "localhost"; /* FIXME */
775 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
780 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
782 return E_OUTOFMEMORY
;
784 sprintf(szCommand
, szCommandFormat
, szHostname
);
786 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
787 SMTPTransport_CallbackReadResponseDoNothing
);
789 HeapFree(GetProcessHeap(), 0, szCommand
);
793 static HRESULT WINAPI
SMTPTransport_CommandHELO(ISMTPTransport2
*iface
)
795 SMTPTransport
*This
= (SMTPTransport
*)iface
;
796 const char szCommandFormat
[] = "HELO %s\n";
797 const char szHostname
[] = "localhost"; /* FIXME */
799 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
804 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
806 return E_OUTOFMEMORY
;
808 sprintf(szCommand
, szCommandFormat
, szHostname
);
810 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
811 SMTPTransport_CallbackReadResponseDoNothing
);
813 HeapFree(GetProcessHeap(), 0, szCommand
);
817 static HRESULT WINAPI
SMTPTransport_CommandAUTH(ISMTPTransport2
*iface
,
820 SMTPTransport
*This
= (SMTPTransport
*)iface
;
821 const char szCommandFormat
[] = "AUTH %s\n";
826 TRACE("(%s)\n", debugstr_a(pszAuthType
));
831 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszAuthType
);
832 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
834 return E_OUTOFMEMORY
;
836 sprintf(szCommand
, szCommandFormat
, pszAuthType
);
838 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
839 SMTPTransport_CallbackReadResponseDoNothing
);
841 HeapFree(GetProcessHeap(), 0, szCommand
);
845 static HRESULT WINAPI
SMTPTransport_CommandQUIT(ISMTPTransport2
*iface
)
847 SMTPTransport
*This
= (SMTPTransport
*)iface
;
851 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_DISCONNECTING
);
852 return InternetTransport_DoCommand(&This
->InetTransport
, "QUIT\n",
853 SMTPTransport_CallbackDisconnect
);
856 static HRESULT WINAPI
SMTPTransport_CommandRSET(ISMTPTransport2
*iface
)
858 SMTPTransport
*This
= (SMTPTransport
*)iface
;
862 return InternetTransport_DoCommand(&This
->InetTransport
, "RSET\n",
863 SMTPTransport_CallbackReadResponseDoNothing
);
866 static HRESULT WINAPI
SMTPTransport_CommandDATA(ISMTPTransport2
*iface
)
868 SMTPTransport
*This
= (SMTPTransport
*)iface
;
872 return InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
873 SMTPTransport_CallbackReadDATAResponse
);
876 static HRESULT WINAPI
SMTPTransport_CommandDOT(ISMTPTransport2
*iface
)
882 static HRESULT WINAPI
SMTPTransport_SendDataStream(ISMTPTransport2
*iface
,
883 IStream
*pStream
, ULONG cbSize
)
885 FIXME("(%p, %d)\n", pStream
, cbSize
);
889 static HRESULT WINAPI
SMTPTransport_SetWindow(ISMTPTransport2
*iface
)
895 static HRESULT WINAPI
SMTPTransport_ResetWindow(ISMTPTransport2
*iface
)
901 static HRESULT WINAPI
SMTPTransport_SendMessage2(ISMTPTransport2
*iface
, LPSMTPMESSAGE2 pMessage
)
903 FIXME("(%p)\n", pMessage
);
907 static HRESULT WINAPI
SMTPTransport_CommandRCPT2(ISMTPTransport2
*iface
, LPSTR pszEmailTo
,
910 FIXME("(%s, %u)\n", pszEmailTo
, atDSN
);
914 static const ISMTPTransport2Vtbl SMTPTransport2Vtbl
=
916 SMTPTransport_QueryInterface
,
917 SMTPTransport_AddRef
,
918 SMTPTransport_Release
,
919 SMTPTransport_GetServerInfo
,
920 SMTPTransport_GetIXPType
,
921 SMTPTransport_IsState
,
922 SMTPTransport_InetServerFromAccount
,
923 SMTPTransport_Connect
,
924 SMTPTransport_HandsOffCallback
,
925 SMTPTransport_Disconnect
,
926 SMTPTransport_DropConnection
,
927 SMTPTransport_GetStatus
,
928 SMTPTransport_InitNew
,
929 SMTPTransport_SendMessage
,
930 SMTPTransport_CommandMAIL
,
931 SMTPTransport_CommandRCPT
,
932 SMTPTransport_CommandEHLO
,
933 SMTPTransport_CommandHELO
,
934 SMTPTransport_CommandAUTH
,
935 SMTPTransport_CommandQUIT
,
936 SMTPTransport_CommandRSET
,
937 SMTPTransport_CommandDATA
,
938 SMTPTransport_CommandDOT
,
939 SMTPTransport_SendDataStream
,
940 SMTPTransport_SetWindow
,
941 SMTPTransport_ResetWindow
,
942 SMTPTransport_SendMessage2
,
943 SMTPTransport_CommandRCPT2
946 HRESULT WINAPI
CreateSMTPTransport(ISMTPTransport
**ppTransport
)
949 SMTPTransport
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
951 return E_OUTOFMEMORY
;
953 This
->InetTransport
.u
.vtblSMTP2
= &SMTPTransport2Vtbl
;
955 This
->fESMTP
= FALSE
;
956 hr
= InternetTransport_Init(&This
->InetTransport
);
959 HeapFree(GetProcessHeap(), 0, This
);
963 *ppTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
964 ISMTPTransport_AddRef(*ppTransport
);
970 static HRESULT WINAPI
SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface
,
971 REFIID riid
, LPVOID
*ppv
)
974 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
977 IClassFactory_AddRef(iface
);
980 return E_NOINTERFACE
;
983 static ULONG WINAPI
SMTPTransportCF_AddRef(LPCLASSFACTORY iface
)
985 return 2; /* non-heap based object */
988 static ULONG WINAPI
SMTPTransportCF_Release(LPCLASSFACTORY iface
)
990 return 1; /* non-heap based object */
993 static HRESULT WINAPI
SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface
,
994 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
997 ISMTPTransport
*pSmtpTransport
;
999 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
1004 return CLASS_E_NOAGGREGATION
;
1006 hr
= CreateSMTPTransport(&pSmtpTransport
);
1010 hr
= ISMTPTransport_QueryInterface(pSmtpTransport
, riid
, ppv
);
1011 ISMTPTransport_Release(pSmtpTransport
);
1016 static HRESULT WINAPI
SMTPTransportCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
1018 FIXME("(%d)\n",fLock
);
1022 static const IClassFactoryVtbl SMTPTransportCFVtbl
=
1024 SMTPTransportCF_QueryInterface
,
1025 SMTPTransportCF_AddRef
,
1026 SMTPTransportCF_Release
,
1027 SMTPTransportCF_CreateInstance
,
1028 SMTPTransportCF_LockServer
1030 static const IClassFactoryVtbl
*SMTPTransportCF
= &SMTPTransportCFVtbl
;
1032 HRESULT
SMTPTransportCF_Create(REFIID riid
, LPVOID
*ppv
)
1034 return IClassFactory_QueryInterface((IClassFactory
*)&SMTPTransportCF
, riid
, ppv
);