ReactOS  0.4.14-dev-337-gf981a68
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 
40 typedef struct
41 {
45  SMTPMESSAGE pending_message;
49 
50 static 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 
107 static 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 
146 static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
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 
180 static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
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 
217 static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
218 {
219  SMTPTransport *This = (SMTPTransport *)iface;
220 
221  TRACE("\n");
223 }
224 
225 static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
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 
269 static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
270 {
271  SMTPTransport *This = (SMTPTransport *)iface;
272 
273  TRACE("\n");
275 }
276 
277 static 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 
327 static 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 
387 static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport *iface, char *pBuffer, int cbBuffer)
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 
447 static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer);
448 
450 {
451  SMTPTransport *This = (SMTPTransport *)iface;
452 
453  TRACE("\n");
455 }
456 
457 static 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 
523  if (IsEqualIID(riid, &IID_IUnknown) ||
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 
910 static 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 
923 static const ISMTPTransport2Vtbl SMTPTransport2Vtbl =
924 {
953 };
954 
956 {
957  HRESULT hr;
958  SMTPTransport *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
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 
979 static HRESULT WINAPI SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface,
980  REFIID riid, LPVOID *ppv)
981 {
982  *ppv = NULL;
984  {
985  *ppv = iface;
986  IClassFactory_AddRef(iface);
987  return S_OK;
988  }
989  return E_NOINTERFACE;
990 }
991 
992 static ULONG WINAPI SMTPTransportCF_AddRef(LPCLASSFACTORY iface)
993 {
994  return 2; /* non-heap based object */
995 }
996 
997 static ULONG WINAPI SMTPTransportCF_Release(LPCLASSFACTORY iface)
998 {
999  return 1; /* non-heap based object */
1000 }
1001 
1002 static HRESULT WINAPI SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface,
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 
1025 static HRESULT WINAPI SMTPTransportCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
1026 {
1027  FIXME("(%d)\n",fLock);
1028  return S_OK;
1029 }
1030 
1031 static const IClassFactoryVtbl SMTPTransportCFVtbl =
1032 {
1038 };
1039 static const IClassFactoryVtbl *SMTPTransportCF = &SMTPTransportCFVtbl;
1040 
1042 {
1043  return IClassFactory_QueryInterface((IClassFactory *)&SMTPTransportCF, riid, ppv);
1044 }
static void SMTPTransport_CallbackMessageReadFromResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
HRESULT WINAPI CreateSMTPTransport(ISMTPTransport **ppTransport)
const DWORD ADDR_TOFROM_MASK
Definition: imnxport.idl:136
static HRESULT WINAPI SMTPTransportCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppv)
static IXPTYPE WINAPI SMTPTransport_GetIXPType(ISMTPTransport2 *iface)
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define E_NOINTERFACE
Definition: winerror.h:2364
HRESULT hr
Definition: shlfolder.c:183
static HRESULT WINAPI SMTPTransport_QueryInterface(ISMTPTransport2 *iface, REFIID riid, void **ppv)
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
static void SMTPTransport_CallbackMessageReadToResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static void SMTPTransport_CallbackDoNothing(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_DropConnection(ISMTPTransport2 *iface)
REFIID riid
Definition: precomp.h:44
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
static HRESULT WINAPI SMTPTransport_CommandQUIT(ISMTPTransport2 *iface)
static void SMTPTransport_CallbackMessageSendTo(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_InitNew(ISMTPTransport2 *iface, LPSTR pszLogFilePath, ISMTPCallback *pCallback)
static ULONG WINAPI SMTPTransportCF_Release(LPCLASSFACTORY iface)
HRESULT InternetTransport_GetStatus(InternetTransport *This, IXPSTATUS *pCurrentStatus) DECLSPEC_HIDDEN
static const IClassFactoryVtbl SMTPTransportCFVtbl
ISF_QUERYAUTHSUPPORT struct INETSERVER * LPINETSERVER
ULONG ulCurrentAddressIndex
Definition: smtptransport.c:47
REFIID LPVOID * ppv
Definition: atlbase.h:39
HRESULT InternetTransport_ChangeStatus(InternetTransport *This, IXPSTATUS Status) DECLSPEC_HIDDEN
HRESULT InternetTransport_HandsOffCallback(InternetTransport *This) DECLSPEC_HIDDEN
static const IClassFactoryVtbl * SMTPTransportCF
static const WCHAR szHostname[]
Definition: CWebService.cpp:10
static HRESULT WINAPI SMTPTransport_SendMessage(ISMTPTransport2 *iface, LPSMTPMESSAGE pMessage)
static void SMTPTransport_CallbackMessageReadDataResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_Disconnect(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_CommandDOT(ISMTPTransport2 *iface)
char * LPSTR
Definition: xmlstorage.h:182
static HRESULT WINAPI SMTPTransportCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
static void SMTPTransport_CallbackProcessDATAResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
HRESULT InternetTransport_InetServerFromAccount(InternetTransport *This, IImnAccount *pAccount, LPINETSERVER pInetServer) DECLSPEC_HIDDEN
#define sprintf(buf, format,...)
Definition: sprintf.c:55
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
static ULONG WINAPI SMTPTransportCF_AddRef(LPCLASSFACTORY iface)
static void SMTPTransport_CallbackSendHello(IInternetTransport *iface, char *pBuffer, int cbBuffer)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static HRESULT WINAPI SMTPTransport_SendDataStream(ISMTPTransport2 *iface, IStream *pStream, ULONG cbSize)
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static LPUNKNOWN
Definition: ndr_ole.c:49
INETADDR * addrlist
Definition: smtptransport.c:46
#define FIXME(fmt,...)
Definition: debug.h:110
#define E_INVALIDARG
Definition: ddrawi.h:101
static void SMTPTransport_CallbackReadDATAResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
smooth NULL
Definition: ftsmooth.c:416
PVOID pBuffer
static HRESULT WINAPI SMTPTransportCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
static HRESULT WINAPI SMTPTransport_CommandRSET(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_InetServerFromAccount(ISMTPTransport2 *iface, IImnAccount *pAccount, LPINETSERVER pInetServer)
static HRESULT WINAPI SMTPTransport_SetWindow(ISMTPTransport2 *iface)
#define debugstr_guid
Definition: kernel32.h:35
#define isdigit(c)
Definition: acclib.h:68
static ULONG WINAPI SMTPTransport_Release(ISMTPTransport2 *iface)
static void SMTPTransport_CallbackDisconnect(IInternetTransport *iface, char *pBuffer, int cbBuffer)
#define TRACE(s)
Definition: solgame.cpp:4
static void SMTPTransport_CallbackProcessRCPTResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
HRESULT InternetTransport_Write(InternetTransport *This, const char *pvData, int cbSize, INETXPORT_COMPLETION_FUNCTION fnCompletion) DECLSPEC_HIDDEN
GLsizeiptr size
Definition: glext.h:5919
enum tagINETADDRTYPE INETADDRTYPE
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static HRESULT WINAPI SMTPTransport_CommandRCPT2(ISMTPTransport2 *iface, LPSTR pszEmailTo, INETADDRTYPE atDSN)
struct tagINETADDR INETADDR
HRESULT InternetTransport_Connect(InternetTransport *This, LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging) DECLSPEC_HIDDEN
#define debugstr_a
Definition: kernel32.h:31
LONG HRESULT
Definition: typedefs.h:77
static void SMTPTransport_CallbackRecvHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
const GUID IID_IUnknown
static HRESULT WINAPI SMTPTransport_CommandMAIL(ISMTPTransport2 *iface, LPSTR pszEmailFrom)
#define WINAPI
Definition: msvc.h:8
static HRESULT WINAPI SMTPTransport_ResetWindow(ISMTPTransport2 *iface)
static ULONG WINAPI SMTPTransport_AddRef(ISMTPTransport2 *iface)
static const ISMTPTransport2Vtbl SMTPTransport2Vtbl
static void SMTPTransport_CallbackReadResponseDoNothing(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_CommandEHLO(ISMTPTransport2 *iface)
static HRESULT WINAPI SMTPTransport_GetServerInfo(ISMTPTransport2 *iface, LPINETSERVER pInetServer)
static HRESULT SMTPTransport_ParseResponse(SMTPTransport *This, char *pszResponse, SMTPRESPONSE *pResponse)
Definition: smtptransport.c:50
InternetTransport InetTransport
Definition: smtptransport.c:42
enum tagIXPTYPE IXPTYPE
#define InterlockedDecrement
Definition: armddk.h:52
static HRESULT WINAPI SMTPTransport_SendMessage2(ISMTPTransport2 *iface, LPSMTPMESSAGE2 pMessage)
static void SMTPTransport_CallbackMessageReadResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_CommandHELO(ISMTPTransport2 *iface)
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define CLASS_E_NOAGGREGATION
Definition: winerror.h:2662
static HRESULT WINAPI SMTPTransport_IsState(ISMTPTransport2 *iface, IXPISSTATE isstate)
#define ERR(fmt,...)
Definition: debug.h:109
static HRESULT WINAPI SMTPTransport_HandsOffCallback(ISMTPTransport2 *iface)
HRESULT InternetTransport_DoCommand(InternetTransport *This, LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion) DECLSPEC_HIDDEN
#define S_OK
Definition: intsafe.h:59
static HRESULT WINAPI SMTPTransport_Connect(ISMTPTransport2 *iface, LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
WINE_DEFAULT_DEBUG_CHANNEL(inetcomm)
#define InterlockedIncrement
Definition: armddk.h:53
#define E_NOTIMPL
Definition: ddrawi.h:99
HRESULT InternetTransport_DropConnection(InternetTransport *This) DECLSPEC_HIDDEN
static void SMTPTransport_CallbackMessageSendDataStream(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static void SMTPTransport_CallbackReadRCPTResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
enum tagIXPSTATUS IXPSTATUS
static void SMTPTransport_CallbackProcessMAILResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static HRESULT WINAPI SMTPTransport_CommandAUTH(ISMTPTransport2 *iface, LPSTR pszAuthType)
static HRESULT WINAPI SMTPTransport_CommandDATA(ISMTPTransport2 *iface)
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
HRESULT SMTPTransportCF_Create(REFIID riid, LPVOID *ppv)
unsigned int ULONG
Definition: retypes.h:1
static HRESULT WINAPI SMTPTransport_GetStatus(ISMTPTransport2 *iface, IXPSTATUS *pCurrentStatus)
static void SMTPTransport_CallbackProcessHelloResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
SMTPMESSAGE pending_message
Definition: smtptransport.c:45
HRESULT InternetTransport_Init(InternetTransport *This) DECLSPEC_HIDDEN
static HRESULT WINAPI SMTPTransport_CommandRCPT(ISMTPTransport2 *iface, LPSTR pszEmailTo)
const GUID IID_IClassFactory
#define memset(x, y, z)
Definition: compat.h:39
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
#define HeapFree(x, y, z)
Definition: compat.h:402
HRESULT InternetTransport_GetServerInfo(InternetTransport *This, LPINETSERVER pInetServer) DECLSPEC_HIDDEN
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
HRESULT InternetTransport_ReadLine(InternetTransport *This, INETXPORT_COMPLETION_FUNCTION fnCompletion) DECLSPEC_HIDDEN
static void SMTPTransport_CallbackMessageSendDOT(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static void SMTPTransport_CallbackMessageProcessResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
static void SMTPTransport_CallbackReadMAILResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)