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 pResponse
->fDone
= (*pszResponse
!= '-');
49 switch (pResponse
->rIxpResult
.uiServerError
)
51 case 211: hrServerError
= IXP_E_SMTP_211_SYSTEM_STATUS
; break;
52 case 214: hrServerError
= IXP_E_SMTP_214_HELP_MESSAGE
; break;
53 case 220: hrServerError
= IXP_E_SMTP_220_READY
; break;
54 case 221: hrServerError
= IXP_E_SMTP_221_CLOSING
; break;
55 case 245: hrServerError
= IXP_E_SMTP_245_AUTH_SUCCESS
; break;
56 case 250: hrServerError
= IXP_E_SMTP_250_MAIL_ACTION_OKAY
; break;
57 case 251: hrServerError
= IXP_E_SMTP_251_FORWARDING_MAIL
; break;
58 case 334: hrServerError
= IXP_E_SMTP_334_AUTH_READY_RESPONSE
; break;
59 case 354: hrServerError
= IXP_E_SMTP_354_START_MAIL_INPUT
; break;
60 case 421: hrServerError
= IXP_E_SMTP_421_NOT_AVAILABLE
; break;
61 case 450: hrServerError
= IXP_E_SMTP_450_MAILBOX_BUSY
; break;
62 case 451: hrServerError
= IXP_E_SMTP_451_ERROR_PROCESSING
; break;
63 case 452: hrServerError
= IXP_E_SMTP_452_NO_SYSTEM_STORAGE
; break;
64 case 454: hrServerError
= IXP_E_SMTP_454_STARTTLS_FAILED
; break;
65 case 500: hrServerError
= IXP_E_SMTP_500_SYNTAX_ERROR
; break;
66 case 501: hrServerError
= IXP_E_SMTP_501_PARAM_SYNTAX
; break;
67 case 502: hrServerError
= IXP_E_SMTP_502_COMMAND_NOTIMPL
; break;
68 case 503: hrServerError
= IXP_E_SMTP_503_COMMAND_SEQ
; break;
69 case 504: hrServerError
= IXP_E_SMTP_504_COMMAND_PARAM_NOTIMPL
; break;
70 case 530: hrServerError
= IXP_E_SMTP_530_STARTTLS_REQUIRED
; break;
71 case 550: hrServerError
= IXP_E_SMTP_550_MAILBOX_NOT_FOUND
; break;
72 case 551: hrServerError
= IXP_E_SMTP_551_USER_NOT_LOCAL
; break;
73 case 552: hrServerError
= IXP_E_SMTP_552_STORAGE_OVERFLOW
; break;
74 case 553: hrServerError
= IXP_E_SMTP_553_MAILBOX_NAME_SYNTAX
; break;
75 case 554: hrServerError
= IXP_E_SMTP_554_TRANSACT_FAILED
; break;
77 hrServerError
= IXP_E_SMTP_RESPONSE_ERROR
;
80 pResponse
->rIxpResult
.hrResult
= hrServerError
;
81 pResponse
->rIxpResult
.hrServerError
= hrServerError
;
83 if (This
->InetTransport
.pCallback
&& This
->InetTransport
.fCommandLogging
)
85 ITransportCallback_OnCommand(This
->InetTransport
.pCallback
, CMD_RESP
,
86 pResponse
->rIxpResult
.pszResponse
, hrServerError
,
87 (IInternetTransport
*)&This
->InetTransport
.u
.vtbl
);
92 static void SMTPTransport_CallbackDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
97 static void SMTPTransport_CallbackReadResponseDoNothing(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
99 SMTPTransport
*This
= (SMTPTransport
*)iface
;
102 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackDoNothing
);
105 static void SMTPTransport_CallbackProcessDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
107 SMTPTransport
*This
= (SMTPTransport
*)iface
;
108 SMTPRESPONSE response
= { 0 };
113 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
116 /* FIXME: handle error */
120 response
.command
= SMTP_DATA
;
121 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
123 if (FAILED(response
.rIxpResult
.hrServerError
))
125 ERR("server error: %s\n", debugstr_a(pBuffer
));
126 /* FIXME: handle error */
131 static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
133 SMTPTransport
*This
= (SMTPTransport
*)iface
;
136 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessDATAResponse
);
139 static void SMTPTransport_CallbackProcessMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
141 SMTPTransport
*This
= (SMTPTransport
*)iface
;
142 SMTPRESPONSE response
= { 0 };
147 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
150 /* FIXME: handle error */
154 response
.command
= SMTP_MAIL
;
155 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
157 if (FAILED(response
.rIxpResult
.hrServerError
))
159 ERR("server error: %s\n", debugstr_a(pBuffer
));
160 /* FIXME: handle error */
165 static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
167 SMTPTransport
*This
= (SMTPTransport
*)iface
;
170 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessMAILResponse
);
173 static void SMTPTransport_CallbackProcessRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
175 SMTPTransport
*This
= (SMTPTransport
*)iface
;
176 SMTPRESPONSE response
= { 0 };
181 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
182 This
->addrlist
= NULL
;
184 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
187 /* FIXME: handle error */
191 response
.command
= SMTP_RCPT
;
192 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
194 if (FAILED(response
.rIxpResult
.hrServerError
))
196 ERR("server error: %s\n", debugstr_a(pBuffer
));
197 /* FIXME: handle error */
202 static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
204 SMTPTransport
*This
= (SMTPTransport
*)iface
;
207 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessRCPTResponse
);
210 static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
212 SMTPTransport
*This
= (SMTPTransport
*)iface
;
213 SMTPRESPONSE response
= { 0 };
218 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
221 /* FIXME: handle error */
225 response
.command
= This
->fESMTP
? SMTP_EHLO
: SMTP_HELO
;
226 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
228 if (FAILED(response
.rIxpResult
.hrServerError
))
230 ERR("server error: %s\n", debugstr_a(pBuffer
));
231 /* FIXME: handle error */
237 InternetTransport_ReadLine(&This
->InetTransport
,
238 SMTPTransport_CallbackProcessHelloResp
);
242 /* FIXME: try to authorize */
244 /* always changed to this status, even if authorization not support on server */
245 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_AUTHORIZED
);
246 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_CONNECTED
);
248 memset(&response
, 0, sizeof(response
));
249 response
.command
= SMTP_CONNECTED
;
250 response
.fDone
= TRUE
;
251 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
254 static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
256 SMTPTransport
*This
= (SMTPTransport
*)iface
;
259 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackProcessHelloResp
);
262 static void SMTPTransport_CallbackSendHello(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
264 SMTPTransport
*This
= (SMTPTransport
*)iface
;
265 SMTPRESPONSE response
= { 0 };
267 const char *pszHello
;
269 const char szHostName
[] = "localhost"; /* FIXME */
273 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
276 /* FIXME: handle error */
280 response
.command
= SMTP_BANNER
;
281 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
283 if (FAILED(response
.rIxpResult
.hrServerError
))
285 ERR("server error: %s\n", debugstr_a(pBuffer
));
286 /* FIXME: handle error */
290 TRACE("(%s)\n", pBuffer
);
292 This
->fESMTP
= strstr(response
.rIxpResult
.pszResponse
, "ESMTP") &&
293 This
->InetTransport
.ServerInfo
.dwFlags
& (ISF_SSLONSAMEPORT
|ISF_QUERYDSNSUPPORT
|ISF_QUERYAUTHSUPPORT
);
300 pszCommand
= HeapAlloc(GetProcessHeap(), 0, strlen(pszHello
) + strlen(szHostName
) + 2);
301 strcpy(pszCommand
, pszHello
);
302 strcat(pszCommand
, szHostName
);
303 pszCommand
[strlen(pszCommand
)+1] = '\0';
304 pszCommand
[strlen(pszCommand
)] = '\n';
306 InternetTransport_DoCommand(&This
->InetTransport
, pszCommand
,
307 SMTPTransport_CallbackRecvHelloResp
);
309 HeapFree(GetProcessHeap(), 0, pszCommand
);
312 static void SMTPTransport_CallbackDisconnect(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
314 SMTPTransport
*This
= (SMTPTransport
*)iface
;
315 SMTPRESPONSE response
;
322 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
325 /* FIXME: handle error */
329 if (FAILED(response
.rIxpResult
.hrServerError
))
331 ERR("server error: %s\n", debugstr_a(pBuffer
));
332 /* FIXME: handle error */
336 InternetTransport_DropConnection(&This
->InetTransport
);
339 static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
341 SMTPTransport
*This
= (SMTPTransport
*)iface
;
342 SMTPRESPONSE response
= { 0 };
347 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
350 /* FIXME: handle error */
354 if (FAILED(response
.rIxpResult
.hrServerError
))
356 ERR("server error: %s\n", debugstr_a(pBuffer
));
357 /* FIXME: handle error */
361 response
.command
= SMTP_SEND_MESSAGE
;
362 response
.rIxpResult
.hrResult
= S_OK
;
363 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
366 static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
368 SMTPTransport
*This
= (SMTPTransport
*)iface
;
369 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageProcessResponse
);
372 static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
374 SMTPTransport
*This
= (SMTPTransport
*)iface
;
376 IStream_Release(This
->pending_message
.pstmMsg
);
377 InternetTransport_DoCommand(&This
->InetTransport
, "\n.\n",
378 SMTPTransport_CallbackMessageReadResponse
);
381 static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
383 SMTPTransport
*This
= (SMTPTransport
*)iface
;
384 SMTPRESPONSE response
;
391 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
394 /* FIXME: handle error */
398 if (FAILED(response
.rIxpResult
.hrServerError
))
400 ERR("server error: %s\n", debugstr_a(pBuffer
));
401 /* FIXME: handle error */
405 pszBuffer
= HeapAlloc(GetProcessHeap(), 0, This
->pending_message
.cbSize
);
406 hr
= IStream_Read(This
->pending_message
.pstmMsg
, pszBuffer
, This
->pending_message
.cbSize
, NULL
);
409 /* FIXME: handle error */
412 cbSize
= This
->pending_message
.cbSize
;
414 /* FIXME: map "\n.\n" to "\n..\n", reallocate memory, update cbSize */
416 /* FIXME: properly stream the message rather than writing it all at once */
418 hr
= InternetTransport_Write(&This
->InetTransport
, pszBuffer
, cbSize
,
419 SMTPTransport_CallbackMessageSendDOT
);
421 HeapFree(GetProcessHeap(), 0, pszBuffer
);
424 static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
426 SMTPTransport
*This
= (SMTPTransport
*)iface
;
429 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendDataStream
);
432 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
);
434 static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
436 SMTPTransport
*This
= (SMTPTransport
*)iface
;
439 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
442 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
444 SMTPTransport
*This
= (SMTPTransport
*)iface
;
445 SMTPRESPONSE response
;
450 hr
= SMTPTransport_ParseResponse(This
, pBuffer
, &response
);
453 /* FIXME: handle error */
457 if (FAILED(response
.rIxpResult
.hrServerError
))
459 ERR("server error: %s\n", debugstr_a(pBuffer
));
460 /* FIXME: handle error */
464 for (; This
->ulCurrentAddressIndex
< This
->pending_message
.rAddressList
.cAddress
; This
->ulCurrentAddressIndex
++)
466 TRACE("address[%d]: %s\n", This
->ulCurrentAddressIndex
,
467 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
469 if ((This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
471 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
473 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ +
474 strlen(This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
476 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
480 sprintf(szCommand
, szCommandFormat
,
481 This
->pending_message
.rAddressList
.prgAddress
[This
->ulCurrentAddressIndex
].szEmail
);
483 This
->ulCurrentAddressIndex
++;
484 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
485 SMTPTransport_CallbackMessageReadToResponse
);
487 HeapFree(GetProcessHeap(), 0, szCommand
);
492 hr
= InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
493 SMTPTransport_CallbackMessageReadDataResponse
);
496 static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport
*iface
, char *pBuffer
, int cbBuffer
)
498 SMTPTransport
*This
= (SMTPTransport
*)iface
;
501 InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackMessageSendTo
);
504 static HRESULT WINAPI
SMTPTransport_QueryInterface(ISMTPTransport2
*iface
, REFIID riid
, void **ppv
)
506 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
508 if (IsEqualIID(riid
, &IID_IUnknown
) ||
509 IsEqualIID(riid
, &IID_IInternetTransport
) ||
510 IsEqualIID(riid
, &IID_ISMTPTransport
) ||
511 IsEqualIID(riid
, &IID_ISMTPTransport2
))
514 ISMTPTransport2_AddRef(iface
);
518 FIXME("no interface for %s\n", debugstr_guid(riid
));
519 return E_NOINTERFACE
;
522 static ULONG WINAPI
SMTPTransport_AddRef(ISMTPTransport2
*iface
)
524 SMTPTransport
*This
= (SMTPTransport
*)iface
;
525 return InterlockedIncrement((LONG
*)&This
->refs
);
528 static ULONG WINAPI
SMTPTransport_Release(ISMTPTransport2
*iface
)
530 SMTPTransport
*This
= (SMTPTransport
*)iface
;
531 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
534 TRACE("destroying %p\n", This
);
535 if (This
->InetTransport
.Status
!= IXP_DISCONNECTED
)
536 InternetTransport_DropConnection(&This
->InetTransport
);
538 if (This
->InetTransport
.pCallback
) ITransportCallback_Release(This
->InetTransport
.pCallback
);
539 HeapFree(GetProcessHeap(), 0, This
->addrlist
);
540 HeapFree(GetProcessHeap(), 0, This
);
545 static HRESULT WINAPI
SMTPTransport_GetServerInfo(ISMTPTransport2
*iface
,
546 LPINETSERVER pInetServer
)
548 SMTPTransport
*This
= (SMTPTransport
*)iface
;
550 TRACE("(%p)\n", pInetServer
);
551 return InternetTransport_GetServerInfo(&This
->InetTransport
, pInetServer
);
554 static IXPTYPE WINAPI
SMTPTransport_GetIXPType(ISMTPTransport2
*iface
)
560 static HRESULT WINAPI
SMTPTransport_IsState(ISMTPTransport2
*iface
,
563 FIXME("(%d): stub\n", isstate
);
567 static HRESULT WINAPI
SMTPTransport_InetServerFromAccount(
568 ISMTPTransport2
*iface
, IImnAccount
*pAccount
, LPINETSERVER pInetServer
)
570 SMTPTransport
*This
= (SMTPTransport
*)iface
;
572 TRACE("(%p, %p)\n", pAccount
, pInetServer
);
573 return InternetTransport_InetServerFromAccount(&This
->InetTransport
, pAccount
, pInetServer
);
576 static HRESULT WINAPI
SMTPTransport_Connect(ISMTPTransport2
*iface
,
577 LPINETSERVER pInetServer
, boolean fAuthenticate
, boolean fCommandLogging
)
579 SMTPTransport
*This
= (SMTPTransport
*)iface
;
582 TRACE("(%p, %s, %s)\n", pInetServer
, fAuthenticate
? "TRUE" : "FALSE", fCommandLogging
? "TRUE" : "FALSE");
584 hr
= InternetTransport_Connect(&This
->InetTransport
, pInetServer
, fAuthenticate
, fCommandLogging
);
588 /* this starts the state machine, which continues in SMTPTransport_CallbackSendHELO */
589 return InternetTransport_ReadLine(&This
->InetTransport
, SMTPTransport_CallbackSendHello
);
592 static HRESULT WINAPI
SMTPTransport_HandsOffCallback(ISMTPTransport2
*iface
)
594 SMTPTransport
*This
= (SMTPTransport
*)iface
;
597 return InternetTransport_HandsOffCallback(&This
->InetTransport
);
600 static HRESULT WINAPI
SMTPTransport_Disconnect(ISMTPTransport2
*iface
)
603 return ISMTPTransport2_CommandQUIT(iface
);
606 static HRESULT WINAPI
SMTPTransport_DropConnection(ISMTPTransport2
*iface
)
608 SMTPTransport
*This
= (SMTPTransport
*)iface
;
611 return InternetTransport_DropConnection(&This
->InetTransport
);
614 static HRESULT WINAPI
SMTPTransport_GetStatus(ISMTPTransport2
*iface
,
615 IXPSTATUS
*pCurrentStatus
)
617 SMTPTransport
*This
= (SMTPTransport
*)iface
;
620 return InternetTransport_GetStatus(&This
->InetTransport
, pCurrentStatus
);
623 static HRESULT WINAPI
SMTPTransport_InitNew(ISMTPTransport2
*iface
,
624 LPSTR pszLogFilePath
, ISMTPCallback
*pCallback
)
626 SMTPTransport
*This
= (SMTPTransport
*)iface
;
628 TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath
), pCallback
);
634 FIXME("not using log file of %s, use Wine debug logging instead\n",
635 debugstr_a(pszLogFilePath
));
637 ISMTPCallback_AddRef(pCallback
);
638 This
->InetTransport
.pCallback
= (ITransportCallback
*)pCallback
;
639 This
->InetTransport
.fInitialised
= TRUE
;
644 static HRESULT WINAPI
SMTPTransport_SendMessage(ISMTPTransport2
*iface
,
645 LPSMTPMESSAGE pMessage
)
647 SMTPTransport
*This
= (SMTPTransport
*)iface
;
649 LPSTR pszFromAddress
= NULL
;
650 const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
655 TRACE("(%p)\n", pMessage
);
657 This
->pending_message
= *pMessage
;
658 IStream_AddRef(pMessage
->pstmMsg
);
660 size
= pMessage
->rAddressList
.cAddress
* sizeof(INETADDR
);
661 This
->addrlist
= HeapAlloc(GetProcessHeap(), 0, size
);
663 return E_OUTOFMEMORY
;
665 memcpy(This
->addrlist
, pMessage
->rAddressList
.prgAddress
, size
);
666 This
->pending_message
.rAddressList
.prgAddress
= This
->addrlist
;
667 This
->ulCurrentAddressIndex
= 0;
669 for (i
= 0; i
< pMessage
->rAddressList
.cAddress
; i
++)
671 if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_FROM
)
673 TRACE("address[%d]: ADDR_FROM, %s\n", i
,
674 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
675 pszFromAddress
= pMessage
->rAddressList
.prgAddress
[i
].szEmail
;
677 else if ((pMessage
->rAddressList
.prgAddress
[i
].addrtype
& ADDR_TOFROM_MASK
) == ADDR_TO
)
679 TRACE("address[%d]: ADDR_TO, %s\n", i
,
680 pMessage
->rAddressList
.prgAddress
[i
].szEmail
);
686 SMTPRESPONSE response
;
687 memset(&response
, 0, sizeof(response
));
688 response
.command
= SMTP_SEND_MESSAGE
;
689 response
.fDone
= TRUE
;
690 response
.pTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
691 response
.rIxpResult
.hrResult
= IXP_E_SMTP_NO_SENDER
;
692 ISMTPCallback_OnResponse((ISMTPCallback
*)This
->InetTransport
.pCallback
, &response
);
695 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszFromAddress
);
697 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
699 return E_OUTOFMEMORY
;
701 sprintf(szCommand
, szCommandFormat
, pszFromAddress
);
703 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
704 SMTPTransport_CallbackMessageReadFromResponse
);
709 static HRESULT WINAPI
SMTPTransport_CommandMAIL(ISMTPTransport2
*iface
, LPSTR pszEmailFrom
)
711 SMTPTransport
*This
= (SMTPTransport
*)iface
;
712 const char szCommandFormat
[] = "MAIL FROM: <%s>\n";
717 TRACE("(%s)\n", debugstr_a(pszEmailFrom
));
722 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailFrom
);
723 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
725 return E_OUTOFMEMORY
;
727 sprintf(szCommand
, szCommandFormat
, pszEmailFrom
);
729 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
730 SMTPTransport_CallbackReadMAILResponse
);
732 HeapFree(GetProcessHeap(), 0, szCommand
);
736 static HRESULT WINAPI
SMTPTransport_CommandRCPT(ISMTPTransport2
*iface
, LPSTR pszEmailTo
)
738 SMTPTransport
*This
= (SMTPTransport
*)iface
;
739 const char szCommandFormat
[] = "RCPT TO: <%s>\n";
744 TRACE("(%s)\n", debugstr_a(pszEmailTo
));
749 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszEmailTo
);
750 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
752 return E_OUTOFMEMORY
;
754 sprintf(szCommand
, szCommandFormat
, pszEmailTo
);
756 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
757 SMTPTransport_CallbackReadRCPTResponse
);
759 HeapFree(GetProcessHeap(), 0, szCommand
);
763 static HRESULT WINAPI
SMTPTransport_CommandEHLO(ISMTPTransport2
*iface
)
765 SMTPTransport
*This
= (SMTPTransport
*)iface
;
766 const char szCommandFormat
[] = "EHLO %s\n";
767 const char szHostname
[] = "localhost"; /* FIXME */
769 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
774 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
776 return E_OUTOFMEMORY
;
778 sprintf(szCommand
, szCommandFormat
, szHostname
);
780 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
781 SMTPTransport_CallbackReadResponseDoNothing
);
783 HeapFree(GetProcessHeap(), 0, szCommand
);
787 static HRESULT WINAPI
SMTPTransport_CommandHELO(ISMTPTransport2
*iface
)
789 SMTPTransport
*This
= (SMTPTransport
*)iface
;
790 const char szCommandFormat
[] = "HELO %s\n";
791 const char szHostname
[] = "localhost"; /* FIXME */
793 int len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + sizeof(szHostname
);
798 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
800 return E_OUTOFMEMORY
;
802 sprintf(szCommand
, szCommandFormat
, szHostname
);
804 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
805 SMTPTransport_CallbackReadResponseDoNothing
);
807 HeapFree(GetProcessHeap(), 0, szCommand
);
811 static HRESULT WINAPI
SMTPTransport_CommandAUTH(ISMTPTransport2
*iface
,
814 SMTPTransport
*This
= (SMTPTransport
*)iface
;
815 const char szCommandFormat
[] = "AUTH %s\n";
820 TRACE("(%s)\n", debugstr_a(pszAuthType
));
825 len
= sizeof(szCommandFormat
) - 2 /* "%s" */ + strlen(pszAuthType
);
826 szCommand
= HeapAlloc(GetProcessHeap(), 0, len
);
828 return E_OUTOFMEMORY
;
830 sprintf(szCommand
, szCommandFormat
, pszAuthType
);
832 hr
= InternetTransport_DoCommand(&This
->InetTransport
, szCommand
,
833 SMTPTransport_CallbackReadResponseDoNothing
);
835 HeapFree(GetProcessHeap(), 0, szCommand
);
839 static HRESULT WINAPI
SMTPTransport_CommandQUIT(ISMTPTransport2
*iface
)
841 SMTPTransport
*This
= (SMTPTransport
*)iface
;
845 InternetTransport_ChangeStatus(&This
->InetTransport
, IXP_DISCONNECTING
);
846 return InternetTransport_DoCommand(&This
->InetTransport
, "QUIT\n",
847 SMTPTransport_CallbackDisconnect
);
850 static HRESULT WINAPI
SMTPTransport_CommandRSET(ISMTPTransport2
*iface
)
852 SMTPTransport
*This
= (SMTPTransport
*)iface
;
856 return InternetTransport_DoCommand(&This
->InetTransport
, "RSET\n",
857 SMTPTransport_CallbackReadResponseDoNothing
);
860 static HRESULT WINAPI
SMTPTransport_CommandDATA(ISMTPTransport2
*iface
)
862 SMTPTransport
*This
= (SMTPTransport
*)iface
;
866 return InternetTransport_DoCommand(&This
->InetTransport
, "DATA\n",
867 SMTPTransport_CallbackReadDATAResponse
);
870 static HRESULT WINAPI
SMTPTransport_CommandDOT(ISMTPTransport2
*iface
)
876 static HRESULT WINAPI
SMTPTransport_SendDataStream(ISMTPTransport2
*iface
,
877 IStream
*pStream
, ULONG cbSize
)
879 FIXME("(%p, %d)\n", pStream
, cbSize
);
883 static HRESULT WINAPI
SMTPTransport_SetWindow(ISMTPTransport2
*iface
)
889 static HRESULT WINAPI
SMTPTransport_ResetWindow(ISMTPTransport2
*iface
)
895 static HRESULT WINAPI
SMTPTransport_SendMessage2(ISMTPTransport2
*iface
, LPSMTPMESSAGE2 pMessage
)
897 FIXME("(%p)\n", pMessage
);
901 static HRESULT WINAPI
SMTPTransport_CommandRCPT2(ISMTPTransport2
*iface
, LPSTR pszEmailTo
,
904 FIXME("(%s, %u)\n", pszEmailTo
, atDSN
);
908 static const ISMTPTransport2Vtbl SMTPTransport2Vtbl
=
910 SMTPTransport_QueryInterface
,
911 SMTPTransport_AddRef
,
912 SMTPTransport_Release
,
913 SMTPTransport_GetServerInfo
,
914 SMTPTransport_GetIXPType
,
915 SMTPTransport_IsState
,
916 SMTPTransport_InetServerFromAccount
,
917 SMTPTransport_Connect
,
918 SMTPTransport_HandsOffCallback
,
919 SMTPTransport_Disconnect
,
920 SMTPTransport_DropConnection
,
921 SMTPTransport_GetStatus
,
922 SMTPTransport_InitNew
,
923 SMTPTransport_SendMessage
,
924 SMTPTransport_CommandMAIL
,
925 SMTPTransport_CommandRCPT
,
926 SMTPTransport_CommandEHLO
,
927 SMTPTransport_CommandHELO
,
928 SMTPTransport_CommandAUTH
,
929 SMTPTransport_CommandQUIT
,
930 SMTPTransport_CommandRSET
,
931 SMTPTransport_CommandDATA
,
932 SMTPTransport_CommandDOT
,
933 SMTPTransport_SendDataStream
,
934 SMTPTransport_SetWindow
,
935 SMTPTransport_ResetWindow
,
936 SMTPTransport_SendMessage2
,
937 SMTPTransport_CommandRCPT2
940 HRESULT WINAPI
CreateSMTPTransport(ISMTPTransport
**ppTransport
)
943 SMTPTransport
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
945 return E_OUTOFMEMORY
;
947 This
->InetTransport
.u
.vtblSMTP2
= &SMTPTransport2Vtbl
;
949 This
->fESMTP
= FALSE
;
950 hr
= InternetTransport_Init(&This
->InetTransport
);
953 HeapFree(GetProcessHeap(), 0, This
);
957 *ppTransport
= (ISMTPTransport
*)&This
->InetTransport
.u
.vtblSMTP2
;
958 ISMTPTransport_AddRef(*ppTransport
);
964 static HRESULT WINAPI
SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface
,
965 REFIID riid
, LPVOID
*ppv
)
968 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
971 IClassFactory_AddRef(iface
);
974 return E_NOINTERFACE
;
977 static ULONG WINAPI
SMTPTransportCF_AddRef(LPCLASSFACTORY iface
)
979 return 2; /* non-heap based object */
982 static ULONG WINAPI
SMTPTransportCF_Release(LPCLASSFACTORY iface
)
984 return 1; /* non-heap based object */
987 static HRESULT WINAPI
SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface
,
988 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
991 ISMTPTransport
*pSmtpTransport
;
993 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
998 return CLASS_E_NOAGGREGATION
;
1000 hr
= CreateSMTPTransport(&pSmtpTransport
);
1004 hr
= ISMTPTransport_QueryInterface(pSmtpTransport
, riid
, ppv
);
1005 ISMTPTransport_Release(pSmtpTransport
);
1010 static HRESULT WINAPI
SMTPTransportCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
1012 FIXME("(%d)\n",fLock
);
1016 static const IClassFactoryVtbl SMTPTransportCFVtbl
=
1018 SMTPTransportCF_QueryInterface
,
1019 SMTPTransportCF_AddRef
,
1020 SMTPTransportCF_Release
,
1021 SMTPTransportCF_CreateInstance
,
1022 SMTPTransportCF_LockServer
1024 static const IClassFactoryVtbl
*SMTPTransportCF
= &SMTPTransportCFVtbl
;
1026 HRESULT
SMTPTransportCF_Create(REFIID riid
, LPVOID
*ppv
)
1028 return IClassFactory_QueryInterface((IClassFactory
*)&SMTPTransportCF
, riid
, ppv
);