ReactOS 0.4.15-dev-8241-g63935f8
smtptransport.c
Go to the documentation of this file.
1/*
2 * SMTP Transport
3 *
4 * Copyright 2006 Robert Shearman for CodeWeavers
5 * Copyright 2008 Hans Leidekker for CodeWeavers
6 *
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.
11 *
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.
16 *
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
20 *
21 */
22
23#define COBJMACROS
24
25#include <stdarg.h>
26#include <stdio.h>
27
28#include "windef.h"
29#include "winbase.h"
30#include "winnt.h"
31#include "winuser.h"
32#include "objbase.h"
33#include "mimeole.h"
34#include "wine/debug.h"
35
36#include "inetcomm_private.h"
37
39
40typedef struct
41{
45 SMTPMESSAGE pending_message;
49
50static HRESULT SMTPTransport_ParseResponse(SMTPTransport *This, char *pszResponse, SMTPRESPONSE *pResponse)
51{
52 HRESULT hrServerError;
53
54 TRACE("response: %s\n", debugstr_a(pszResponse));
55
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 != '-');
63
64 switch (pResponse->rIxpResult.uiServerError)
65 {
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;
91 default:
92 hrServerError = IXP_E_SMTP_RESPONSE_ERROR;
93 break;
94 }
95 pResponse->rIxpResult.hrResult = hrServerError;
96 pResponse->rIxpResult.hrServerError = hrServerError;
97
98 if (This->InetTransport.pCallback && This->InetTransport.fCommandLogging)
99 {
100 ITransportCallback_OnCommand(This->InetTransport.pCallback, CMD_RESP,
101 pResponse->rIxpResult.pszResponse, hrServerError,
102 (IInternetTransport *)&This->InetTransport.u.vtbl);
103 }
104 return S_OK;
105}
106
107static void SMTPTransport_CallbackDoNothing(IInternetTransport *iface, char *pBuffer, int cbBuffer)
108{
109 TRACE("\n");
110}
111
113{
114 SMTPTransport *This = (SMTPTransport *)iface;
115
116 TRACE("\n");
118}
119
121{
122 SMTPTransport *This = (SMTPTransport *)iface;
123 SMTPRESPONSE response = { 0 };
124 HRESULT hr;
125
126 TRACE("\n");
127
129 if (FAILED(hr))
130 {
131 /* FIXME: handle error */
132 return;
133 }
134
135 response.command = SMTP_DATA;
136 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
137
138 if (FAILED(response.rIxpResult.hrServerError))
139 {
140 ERR("server error: %s\n", debugstr_a(pBuffer));
141 /* FIXME: handle error */
142 return;
143 }
144}
145
147{
148 SMTPTransport *This = (SMTPTransport *)iface;
149
150 TRACE("\n");
152}
153
155{
156 SMTPTransport *This = (SMTPTransport *)iface;
157 SMTPRESPONSE response = { 0 };
158 HRESULT hr;
159
160 TRACE("\n");
161
163 if (FAILED(hr))
164 {
165 /* FIXME: handle error */
166 return;
167 }
168
169 response.command = SMTP_MAIL;
170 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
171
172 if (FAILED(response.rIxpResult.hrServerError))
173 {
174 ERR("server error: %s\n", debugstr_a(pBuffer));
175 /* FIXME: handle error */
176 return;
177 }
178}
179
181{
182 SMTPTransport *This = (SMTPTransport *)iface;
183
184 TRACE("\n");
186}
187
189{
190 SMTPTransport *This = (SMTPTransport *)iface;
191 SMTPRESPONSE response = { 0 };
192 HRESULT hr;
193
194 TRACE("\n");
195
196 HeapFree(GetProcessHeap(), 0, This->addrlist);
197 This->addrlist = NULL;
198
200 if (FAILED(hr))
201 {
202 /* FIXME: handle error */
203 return;
204 }
205
206 response.command = SMTP_RCPT;
207 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
208
209 if (FAILED(response.rIxpResult.hrServerError))
210 {
211 ERR("server error: %s\n", debugstr_a(pBuffer));
212 /* FIXME: handle error */
213 return;
214 }
215}
216
218{
219 SMTPTransport *This = (SMTPTransport *)iface;
220
221 TRACE("\n");
223}
224
226{
227 SMTPTransport *This = (SMTPTransport *)iface;
228 SMTPRESPONSE response = { 0 };
229 HRESULT hr;
230
231 TRACE("\n");
232
234 if (FAILED(hr))
235 {
236 /* FIXME: handle error */
237 return;
238 }
239
240 response.command = This->fESMTP ? SMTP_EHLO : SMTP_HELO;
241 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
242
243 if (FAILED(response.rIxpResult.hrServerError))
244 {
245 ERR("server error: %s\n", debugstr_a(pBuffer));
246 /* FIXME: handle error */
247 return;
248 }
249
250 if (!response.fDone)
251 {
252 InternetTransport_ReadLine(&This->InetTransport,
254 return;
255 }
256
257 /* FIXME: try to authorize */
258
259 /* always changed to this status, even if authorization not support on server */
262
263 memset(&response, 0, sizeof(response));
264 response.command = SMTP_CONNECTED;
265 response.fDone = TRUE;
266 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
267}
268
269static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
270{
271 SMTPTransport *This = (SMTPTransport *)iface;
272
273 TRACE("\n");
275}
276
277static void SMTPTransport_CallbackSendHello(IInternetTransport *iface, char *pBuffer, int cbBuffer)
278{
279 SMTPTransport *This = (SMTPTransport *)iface;
280 SMTPRESPONSE response = { 0 };
281 HRESULT hr;
282 const char *pszHello;
283 char *pszCommand;
284 static const char szHostName[] = "localhost"; /* FIXME */
285
286 TRACE("\n");
287
289 if (FAILED(hr))
290 {
291 /* FIXME: handle error */
292 return;
293 }
294
295 response.command = SMTP_BANNER;
296 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
297
298 if (FAILED(response.rIxpResult.hrServerError))
299 {
300 ERR("server error: %s\n", debugstr_a(pBuffer));
301 /* FIXME: handle error */
302 return;
303 }
304
305 TRACE("(%s)\n", pBuffer);
306
307 This->fESMTP = strstr(response.rIxpResult.pszResponse, "ESMTP") &&
308 This->InetTransport.ServerInfo.dwFlags & (ISF_SSLONSAMEPORT|ISF_QUERYDSNSUPPORT|ISF_QUERYAUTHSUPPORT);
309
310 if (This->fESMTP)
311 pszHello = "EHLO ";
312 else
313 pszHello = "HELO ";
314
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';
320
321 InternetTransport_DoCommand(&This->InetTransport, pszCommand,
323
324 HeapFree(GetProcessHeap(), 0, pszCommand);
325}
326
327static void SMTPTransport_CallbackDisconnect(IInternetTransport *iface, char *pBuffer, int cbBuffer)
328{
329 SMTPTransport *This = (SMTPTransport *)iface;
330 SMTPRESPONSE response;
331 HRESULT hr;
332
333 TRACE("\n");
334
335 if (pBuffer)
336 {
338 if (FAILED(hr))
339 {
340 /* FIXME: handle error */
341 return;
342 }
343
344 if (FAILED(response.rIxpResult.hrServerError))
345 {
346 ERR("server error: %s\n", debugstr_a(pBuffer));
347 /* FIXME: handle error */
348 return;
349 }
350 }
351 InternetTransport_DropConnection(&This->InetTransport);
352}
353
355{
356 SMTPTransport *This = (SMTPTransport *)iface;
357 SMTPRESPONSE response = { 0 };
358 HRESULT hr;
359
360 TRACE("\n");
361
363 if (FAILED(hr))
364 {
365 /* FIXME: handle error */
366 return;
367 }
368
369 if (FAILED(response.rIxpResult.hrServerError))
370 {
371 ERR("server error: %s\n", debugstr_a(pBuffer));
372 /* FIXME: handle error */
373 return;
374 }
375
376 response.command = SMTP_SEND_MESSAGE;
377 response.rIxpResult.hrResult = S_OK;
378 ISMTPCallback_OnResponse((ISMTPCallback *)This->InetTransport.pCallback, &response);
379}
380
382{
383 SMTPTransport *This = (SMTPTransport *)iface;
385}
386
388{
389 SMTPTransport *This = (SMTPTransport *)iface;
390
391 IStream_Release(This->pending_message.pstmMsg);
392 InternetTransport_DoCommand(&This->InetTransport, "\n.\n",
394}
395
397{
398 SMTPTransport *This = (SMTPTransport *)iface;
399 SMTPRESPONSE response;
400 HRESULT hr;
401 char *pszBuffer;
402 ULONG cbSize;
403
404 TRACE("\n");
405
407 if (FAILED(hr))
408 {
409 /* FIXME: handle error */
410 return;
411 }
412
413 if (FAILED(response.rIxpResult.hrServerError))
414 {
415 ERR("server error: %s\n", debugstr_a(pBuffer));
416 /* FIXME: handle error */
417 return;
418 }
419
420 pszBuffer = HeapAlloc(GetProcessHeap(), 0, This->pending_message.cbSize);
421 hr = IStream_Read(This->pending_message.pstmMsg, pszBuffer, This->pending_message.cbSize, NULL);
422 if (FAILED(hr))
423 {
424 /* FIXME: handle error */
425 return;
426 }
427 cbSize = This->pending_message.cbSize;
428
429 /* FIXME: map "\n.\n" to "\n..\n", reallocate memory, update cbSize */
430
431 /* FIXME: properly stream the message rather than writing it all at once */
432
433 hr = InternetTransport_Write(&This->InetTransport, pszBuffer, cbSize,
435
436 HeapFree(GetProcessHeap(), 0, pszBuffer);
437}
438
440{
441 SMTPTransport *This = (SMTPTransport *)iface;
442
443 TRACE("\n");
445}
446
447static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer);
448
450{
451 SMTPTransport *This = (SMTPTransport *)iface;
452
453 TRACE("\n");
455}
456
457static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer)
458{
459 SMTPTransport *This = (SMTPTransport *)iface;
460 SMTPRESPONSE response;
461 HRESULT hr;
462
463 TRACE("\n");
464
466 if (FAILED(hr))
467 {
468 /* FIXME: handle error */
469 return;
470 }
471
472 if (FAILED(response.rIxpResult.hrServerError))
473 {
474 ERR("server error: %s\n", debugstr_a(pBuffer));
475 /* FIXME: handle error */
476 return;
477 }
478
479 for (; This->ulCurrentAddressIndex < This->pending_message.rAddressList.cAddress; This->ulCurrentAddressIndex++)
480 {
481 TRACE("address[%d]: %s\n", This->ulCurrentAddressIndex,
482 This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail);
483
484 if ((This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].addrtype & ADDR_TOFROM_MASK) == ADDR_TO)
485 {
486 static const char szCommandFormat[] = "RCPT TO: <%s>\n";
487 char *szCommand;
488 int len = sizeof(szCommandFormat) - 2 /* "%s" */ +
489 strlen(This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail);
490
491 szCommand = HeapAlloc(GetProcessHeap(), 0, len);
492 if (!szCommand)
493 return;
494
495 sprintf(szCommand, szCommandFormat,
496 This->pending_message.rAddressList.prgAddress[This->ulCurrentAddressIndex].szEmail);
497
498 This->ulCurrentAddressIndex++;
499 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
501
502 HeapFree(GetProcessHeap(), 0, szCommand);
503 return;
504 }
505 }
506
507 hr = InternetTransport_DoCommand(&This->InetTransport, "DATA\n",
509}
510
512{
513 SMTPTransport *This = (SMTPTransport *)iface;
514
515 TRACE("\n");
517}
518
520{
521 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
522
524 IsEqualIID(riid, &IID_IInternetTransport) ||
525 IsEqualIID(riid, &IID_ISMTPTransport) ||
526 IsEqualIID(riid, &IID_ISMTPTransport2))
527 {
528 *ppv = iface;
529 ISMTPTransport2_AddRef(iface);
530 return S_OK;
531 }
532 *ppv = NULL;
533 FIXME("no interface for %s\n", debugstr_guid(riid));
534 return E_NOINTERFACE;
535}
536
538{
539 SMTPTransport *This = (SMTPTransport *)iface;
540 return InterlockedIncrement((LONG *)&This->refs);
541}
542
544{
545 SMTPTransport *This = (SMTPTransport *)iface;
546 ULONG refs = InterlockedDecrement((LONG *)&This->refs);
547 if (!refs)
548 {
549 TRACE("destroying %p\n", This);
550 if (This->InetTransport.Status != IXP_DISCONNECTED)
551 InternetTransport_DropConnection(&This->InetTransport);
552
553 if (This->InetTransport.pCallback) ITransportCallback_Release(This->InetTransport.pCallback);
554 HeapFree(GetProcessHeap(), 0, This->addrlist);
556 }
557 return refs;
558}
559
561 LPINETSERVER pInetServer)
562{
563 SMTPTransport *This = (SMTPTransport *)iface;
564
565 TRACE("(%p)\n", pInetServer);
566 return InternetTransport_GetServerInfo(&This->InetTransport, pInetServer);
567}
568
570{
571 TRACE("()\n");
572 return IXP_SMTP;
573}
574
576 IXPISSTATE isstate)
577{
578 FIXME("(%d): stub\n", isstate);
579 return E_NOTIMPL;
580}
581
583 ISMTPTransport2 *iface, IImnAccount *pAccount, LPINETSERVER pInetServer)
584{
585 SMTPTransport *This = (SMTPTransport *)iface;
586
587 TRACE("(%p, %p)\n", pAccount, pInetServer);
588 return InternetTransport_InetServerFromAccount(&This->InetTransport, pAccount, pInetServer);
589}
590
592 LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
593{
594 SMTPTransport *This = (SMTPTransport *)iface;
595 HRESULT hr;
596
597 TRACE("(%p, %s, %s)\n", pInetServer, fAuthenticate ? "TRUE" : "FALSE", fCommandLogging ? "TRUE" : "FALSE");
598
599 hr = InternetTransport_Connect(&This->InetTransport, pInetServer, fAuthenticate, fCommandLogging);
600 if (FAILED(hr))
601 return hr;
602
603 /* this starts the state machine, which continues in SMTPTransport_CallbackSendHELO */
605}
606
608{
609 SMTPTransport *This = (SMTPTransport *)iface;
610
611 TRACE("()\n");
612 return InternetTransport_HandsOffCallback(&This->InetTransport);
613}
614
616{
617 TRACE("()\n");
618 return ISMTPTransport2_CommandQUIT(iface);
619}
620
622{
623 SMTPTransport *This = (SMTPTransport *)iface;
624
625 TRACE("()\n");
626 return InternetTransport_DropConnection(&This->InetTransport);
627}
628
630 IXPSTATUS *pCurrentStatus)
631{
632 SMTPTransport *This = (SMTPTransport *)iface;
633
634 TRACE("()\n");
635 return InternetTransport_GetStatus(&This->InetTransport, pCurrentStatus);
636}
637
639 LPSTR pszLogFilePath, ISMTPCallback *pCallback)
640{
641 SMTPTransport *This = (SMTPTransport *)iface;
642
643 TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath), pCallback);
644
645 if (!pCallback)
646 return E_INVALIDARG;
647
648 if (pszLogFilePath)
649 FIXME("not using log file of %s, use Wine debug logging instead\n",
650 debugstr_a(pszLogFilePath));
651
652 ISMTPCallback_AddRef(pCallback);
653 This->InetTransport.pCallback = (ITransportCallback *)pCallback;
654 This->InetTransport.fInitialised = TRUE;
655
656 return S_OK;
657}
658
660 LPSMTPMESSAGE pMessage)
661{
662 static const char szCommandFormat[] = "MAIL FROM: <%s>\n";
663 SMTPTransport *This = (SMTPTransport *)iface;
664 ULONG i, size;
665 LPSTR pszFromAddress = NULL;
666 char *szCommand;
667 int len;
668 HRESULT hr;
669
670 TRACE("(%p)\n", pMessage);
671
672 This->pending_message = *pMessage;
673 IStream_AddRef(pMessage->pstmMsg);
674
675 size = pMessage->rAddressList.cAddress * sizeof(INETADDR);
676 This->addrlist = HeapAlloc(GetProcessHeap(), 0, size);
677 if (!This->addrlist)
678 return E_OUTOFMEMORY;
679
680 memcpy(This->addrlist, pMessage->rAddressList.prgAddress, size);
681 This->pending_message.rAddressList.prgAddress = This->addrlist;
682 This->ulCurrentAddressIndex = 0;
683
684 for (i = 0; i < pMessage->rAddressList.cAddress; i++)
685 {
686 if ((pMessage->rAddressList.prgAddress[i].addrtype & ADDR_TOFROM_MASK) == ADDR_FROM)
687 {
688 TRACE("address[%d]: ADDR_FROM, %s\n", i,
689 pMessage->rAddressList.prgAddress[i].szEmail);
690 pszFromAddress = pMessage->rAddressList.prgAddress[i].szEmail;
691 }
692 else if ((pMessage->rAddressList.prgAddress[i].addrtype & ADDR_TOFROM_MASK) == ADDR_TO)
693 {
694 TRACE("address[%d]: ADDR_TO, %s\n", i,
695 pMessage->rAddressList.prgAddress[i].szEmail);
696 }
697 }
698
699 if (!pszFromAddress)
700 {
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);
708 return S_OK;
709 }
710 len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszFromAddress);
711
712 szCommand = HeapAlloc(GetProcessHeap(), 0, len);
713 if (!szCommand)
714 return E_OUTOFMEMORY;
715
716 sprintf(szCommand, szCommandFormat, pszFromAddress);
717
718 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
720
721 return hr;
722}
723
725{
726 static const char szCommandFormat[] = "MAIL FROM: <%s>\n";
727 SMTPTransport *This = (SMTPTransport *)iface;
728 char *szCommand;
729 int len;
730 HRESULT hr;
731
732 TRACE("(%s)\n", debugstr_a(pszEmailFrom));
733
734 if (!pszEmailFrom)
735 return E_INVALIDARG;
736
737 len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailFrom);
738 szCommand = HeapAlloc(GetProcessHeap(), 0, len);
739 if (!szCommand)
740 return E_OUTOFMEMORY;
741
742 sprintf(szCommand, szCommandFormat, pszEmailFrom);
743
744 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
746
747 HeapFree(GetProcessHeap(), 0, szCommand);
748 return hr;
749}
750
752{
753 static const char szCommandFormat[] = "RCPT TO: <%s>\n";
754 SMTPTransport *This = (SMTPTransport *)iface;
755 char *szCommand;
756 int len;
757 HRESULT hr;
758
759 TRACE("(%s)\n", debugstr_a(pszEmailTo));
760
761 if (!pszEmailTo)
762 return E_INVALIDARG;
763
764 len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailTo);
765 szCommand = HeapAlloc(GetProcessHeap(), 0, len);
766 if (!szCommand)
767 return E_OUTOFMEMORY;
768
769 sprintf(szCommand, szCommandFormat, pszEmailTo);
770
771 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
773
774 HeapFree(GetProcessHeap(), 0, szCommand);
775 return hr;
776}
777
779{
780 static const char szCommandFormat[] = "EHLO %s\n";
781 static const char szHostname[] = "localhost"; /* FIXME */
782 SMTPTransport *This = (SMTPTransport *)iface;
783 char *szCommand;
784 int len = sizeof(szCommandFormat) - 2 /* "%s" */ + sizeof(szHostname);
785 HRESULT hr;
786
787 TRACE("\n");
788
789 szCommand = HeapAlloc(GetProcessHeap(), 0, len);
790 if (!szCommand)
791 return E_OUTOFMEMORY;
792
793 sprintf(szCommand, szCommandFormat, szHostname);
794
795 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
797
798 HeapFree(GetProcessHeap(), 0, szCommand);
799 return hr;
800}
801
803{
804 static const char szCommandFormat[] = "HELO %s\n";
805 static const char szHostname[] = "localhost"; /* FIXME */
806 SMTPTransport *This = (SMTPTransport *)iface;
807 char *szCommand;
808 int len = sizeof(szCommandFormat) - 2 /* "%s" */ + sizeof(szHostname);
809 HRESULT hr;
810
811 TRACE("()\n");
812
813 szCommand = HeapAlloc(GetProcessHeap(), 0, len);
814 if (!szCommand)
815 return E_OUTOFMEMORY;
816
817 sprintf(szCommand, szCommandFormat, szHostname);
818
819 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
821
822 HeapFree(GetProcessHeap(), 0, szCommand);
823 return hr;
824}
825
827 LPSTR pszAuthType)
828{
829 static const char szCommandFormat[] = "AUTH %s\n";
830 SMTPTransport *This = (SMTPTransport *)iface;
831 char *szCommand;
832 int len;
833 HRESULT hr;
834
835 TRACE("(%s)\n", debugstr_a(pszAuthType));
836
837 if (!pszAuthType)
838 return E_INVALIDARG;
839
840 len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszAuthType);
841 szCommand = HeapAlloc(GetProcessHeap(), 0, len);
842 if (!szCommand)
843 return E_OUTOFMEMORY;
844
845 sprintf(szCommand, szCommandFormat, pszAuthType);
846
847 hr = InternetTransport_DoCommand(&This->InetTransport, szCommand,
849
850 HeapFree(GetProcessHeap(), 0, szCommand);
851 return hr;
852}
853
855{
856 SMTPTransport *This = (SMTPTransport *)iface;
857
858 TRACE("()\n");
859
861 return InternetTransport_DoCommand(&This->InetTransport, "QUIT\n",
863}
864
866{
867 SMTPTransport *This = (SMTPTransport *)iface;
868
869 TRACE("()\n");
870
871 return InternetTransport_DoCommand(&This->InetTransport, "RSET\n",
873}
874
876{
877 SMTPTransport *This = (SMTPTransport *)iface;
878
879 TRACE("()\n");
880
881 return InternetTransport_DoCommand(&This->InetTransport, "DATA\n",
883}
884
886{
887 FIXME("()\n");
888 return E_NOTIMPL;
889}
890
892 IStream *pStream, ULONG cbSize)
893{
894 FIXME("(%p, %d)\n", pStream, cbSize);
895 return E_NOTIMPL;
896}
897
899{
900 FIXME("()\n");
901 return E_NOTIMPL;
902}
903
905{
906 FIXME("()\n");
907 return E_NOTIMPL;
908}
909
910static HRESULT WINAPI SMTPTransport_SendMessage2(ISMTPTransport2 *iface, LPSMTPMESSAGE2 pMessage)
911{
912 FIXME("(%p)\n", pMessage);
913 return E_NOTIMPL;
914}
915
917 INETADDRTYPE atDSN)
918{
919 FIXME("(%s, %u)\n", pszEmailTo, atDSN);
920 return E_NOTIMPL;
921}
922
923static const ISMTPTransport2Vtbl SMTPTransport2Vtbl =
924{
953};
954
956{
957 HRESULT hr;
959 if (!This)
960 return E_OUTOFMEMORY;
961
962 This->InetTransport.u.vtblSMTP2 = &SMTPTransport2Vtbl;
963 This->refs = 0;
964 This->fESMTP = FALSE;
965 hr = InternetTransport_Init(&This->InetTransport);
966 if (FAILED(hr))
967 {
969 return hr;
970 }
971
972 *ppTransport = (ISMTPTransport *)&This->InetTransport.u.vtblSMTP2;
973 ISMTPTransport_AddRef(*ppTransport);
974
975 return S_OK;
976}
977
978
981{
982 *ppv = NULL;
984 {
985 *ppv = iface;
986 IClassFactory_AddRef(iface);
987 return S_OK;
988 }
989 return E_NOINTERFACE;
990}
991
992static ULONG WINAPI SMTPTransportCF_AddRef(LPCLASSFACTORY iface)
993{
994 return 2; /* non-heap based object */
995}
996
997static ULONG WINAPI SMTPTransportCF_Release(LPCLASSFACTORY iface)
998{
999 return 1; /* non-heap based object */
1000}
1001
1004{
1005 HRESULT hr;
1006 ISMTPTransport *pSmtpTransport;
1007
1008 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
1009
1010 *ppv = NULL;
1011
1012 if (pUnk)
1013 return CLASS_E_NOAGGREGATION;
1014
1015 hr = CreateSMTPTransport(&pSmtpTransport);
1016 if (FAILED(hr))
1017 return hr;
1018
1019 hr = ISMTPTransport_QueryInterface(pSmtpTransport, riid, ppv);
1020 ISMTPTransport_Release(pSmtpTransport);
1021
1022 return hr;
1023}
1024
1025static HRESULT WINAPI SMTPTransportCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
1026{
1027 FIXME("(%d)\n",fLock);
1028 return S_OK;
1029}
1030
1031static const IClassFactoryVtbl SMTPTransportCFVtbl =
1032{
1038};
1039static const IClassFactoryVtbl *SMTPTransportCF = &SMTPTransportCFVtbl;
1040
1042{
1043 return IClassFactory_QueryInterface((IClassFactory *)&SMTPTransportCF, riid, ppv);
1044}
static const WCHAR szHostname[]
Definition: CWebService.cpp:10
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
#define isdigit(c)
Definition: acclib.h:68
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
const GUID IID_IUnknown
const GUID IID_IClassFactory
#define FIXME(fmt,...)
Definition: debug.h:114
#define ERR(fmt,...)
Definition: debug.h:113
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
unsigned int BOOL
Definition: ntddk_ex.h:94
FxPnpStateCallbackInfo * pCallback
GLsizeiptr size
Definition: glext.h:5919
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
@ IXP_DISCONNECTING
Definition: imnxport.idl:252
@ IXP_CONNECTED
Definition: imnxport.idl:248
@ IXP_AUTHORIZED
Definition: imnxport.idl:251
@ IXP_DISCONNECTED
Definition: imnxport.idl:253
enum tagINETADDRTYPE INETADDRTYPE
const DWORD ADDR_TOFROM_MASK
Definition: imnxport.idl:136
struct tagINETADDR INETADDR
enum tagIXPTYPE IXPTYPE
@ IXP_SMTP
Definition: imnxport.idl:236
@ ADDR_FROM
Definition: imnxport.idl:129
@ ADDR_TO
Definition: imnxport.idl:128
enum tagIXPSTATUS IXPSTATUS
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
HRESULT InternetTransport_InetServerFromAccount(InternetTransport *This, IImnAccount *pAccount, LPINETSERVER pInetServer) DECLSPEC_HIDDEN
HRESULT InternetTransport_DropConnection(InternetTransport *This) DECLSPEC_HIDDEN
HRESULT InternetTransport_Write(InternetTransport *This, const char *pvData, int cbSize, INETXPORT_COMPLETION_FUNCTION fnCompletion) DECLSPEC_HIDDEN
HRESULT InternetTransport_DoCommand(InternetTransport *This, LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion) DECLSPEC_HIDDEN
HRESULT InternetTransport_GetServerInfo(InternetTransport *This, LPINETSERVER pInetServer) DECLSPEC_HIDDEN
HRESULT InternetTransport_GetStatus(InternetTransport *This, IXPSTATUS *pCurrentStatus) DECLSPEC_HIDDEN
HRESULT InternetTransport_ReadLine(InternetTransport *This, INETXPORT_COMPLETION_FUNCTION fnCompletion) DECLSPEC_HIDDEN
HRESULT InternetTransport_Init(InternetTransport *This) DECLSPEC_HIDDEN
HRESULT InternetTransport_HandsOffCallback(InternetTransport *This) DECLSPEC_HIDDEN
HRESULT InternetTransport_Connect(InternetTransport *This, LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging) DECLSPEC_HIDDEN
HRESULT InternetTransport_ChangeStatus(InternetTransport *This, IXPSTATUS Status) DECLSPEC_HIDDEN
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_a
Definition: kernel32.h:31
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static LPUNKNOWN
Definition: ndr_ole.c:49
long LONG
Definition: pedump.c:60
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
PVOID pBuffer
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
static HRESULT WINAPI SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppv)
static void SMTPTransport_CallbackReadResponseDoNothing(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_InetServerFromAccount(ISMTPTransport2 *iface, IImnAccount *pAccount, LPINETSERVER pInetServer)
static void SMTPTransport_CallbackProcessDATAResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_DropConnection(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_CommandMAIL(ISMTPTransport2 *iface, LPSTR pszEmailFrom)
static void SMTPTransport_CallbackSendHello(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static ULONG WINAPI SMTPTransport_AddRef(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_CommandHELO(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_SendDataStream(ISMTPTransport2 *iface, IStream *pStream, ULONG cbSize)
static HRESULT WINAPI SMTPTransport_IsState(ISMTPTransport2 *iface, IXPISSTATE isstate)
static HRESULT WINAPI SMTPTransportCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
static HRESULT WINAPI SMTPTransport_GetStatus(ISMTPTransport2 *iface, IXPSTATUS *pCurrentStatus)
static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_GetServerInfo(ISMTPTransport2 *iface, LPINETSERVER pInetServer)
HRESULT WINAPI CreateSMTPTransport(ISMTPTransport **ppTransport)
static const ISMTPTransport2Vtbl SMTPTransport2Vtbl
static void SMTPTransport_CallbackDoNothing(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_CommandEHLO(ISMTPTransport2 *iface)
static void SMTPTransport_CallbackProcessRCPTResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_CommandDOT(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_CommandRCPT2(ISMTPTransport2 *iface, LPSTR pszEmailTo, INETADDRTYPE atDSN)
static HRESULT WINAPI SMTPTransport_QueryInterface(ISMTPTransport2 *iface, REFIID riid, void **ppv)
static HRESULT WINAPI SMTPTransport_SetWindow(ISMTPTransport2 *iface)
static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static ULONG WINAPI SMTPTransport_Release(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_Connect(ISMTPTransport2 *iface, LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
static HRESULT WINAPI SMTPTransport_ResetWindow(ISMTPTransport2 *iface)
HRESULT SMTPTransportCF_Create(REFIID riid, LPVOID *ppv)
static void SMTPTransport_CallbackProcessMAILResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT SMTPTransport_ParseResponse(SMTPTransport *This, char *pszResponse, SMTPRESPONSE *pResponse)
Definition: smtptransport.c:50
static IXPTYPE WINAPI SMTPTransport_GetIXPType(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_CommandDATA(ISMTPTransport2 *iface)
static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static const IClassFactoryVtbl SMTPTransportCFVtbl
static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_HandsOffCallback(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_CommandRCPT(ISMTPTransport2 *iface, LPSTR pszEmailTo)
static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_CommandRSET(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_Disconnect(ISMTPTransport2 *iface)
static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_CommandQUIT(ISMTPTransport2 *iface)
static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_CommandAUTH(ISMTPTransport2 *iface, LPSTR pszAuthType)
static ULONG WINAPI SMTPTransportCF_AddRef(LPCLASSFACTORY iface)
static HRESULT WINAPI SMTPTransport_SendMessage(ISMTPTransport2 *iface, LPSMTPMESSAGE pMessage)
static ULONG WINAPI SMTPTransportCF_Release(LPCLASSFACTORY iface)
static void SMTPTransport_CallbackDisconnect(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_SendMessage2(ISMTPTransport2 *iface, LPSMTPMESSAGE2 pMessage)
static HRESULT WINAPI SMTPTransport_InitNew(ISMTPTransport2 *iface, LPSTR pszLogFilePath, ISMTPCallback *pCallback)
static const IClassFactoryVtbl * SMTPTransportCF
#define TRACE(s)
Definition: solgame.cpp:4
SMTPMESSAGE pending_message
Definition: smtptransport.c:45
InternetTransport InetTransport
Definition: smtptransport.c:42
ULONG ulCurrentAddressIndex
Definition: smtptransport.c:47
INETADDR * addrlist
Definition: smtptransport.c:46
uint32_t ULONG
Definition: typedefs.h:59
#define WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:2364
#define CLASS_E_NOAGGREGATION
Definition: winerror.h:2662
char * LPSTR
Definition: xmlstorage.h:182