Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
6.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. // SMTP RFC 821 Specifies <CR><LF> to terminate lines.
  8. //
  9. // <CR> = Carriage Return C: \r Dec: 13 Hex: 0x0d Oct: 0015
  10. // <LF> = Line Feed ( Newline ) C: \n Dec: 10 Hex: 0x0a Oct: 0012
  11. //
  12. //=============================================================================//
  13. #pragma warning( disable : 4530 )
  14. #include <string>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <stdarg.h>
  18. #include <time.h>
  19. #include "simplesocket.h"
  20. static int g_ArgCount;
  21. static char **g_Args;
  22. //-----------------------------------------------------------------------------
  23. // Purpose: simple args API
  24. // Input : argc -
  25. // *argv[] -
  26. //-----------------------------------------------------------------------------
  27. void ArgsInit( int argc, char *argv[] )
  28. {
  29. g_ArgCount = argc;
  30. g_Args = argv;
  31. }
  32. //-----------------------------------------------------------------------------
  33. // Purpose: tests for the presence of arg "pName"
  34. // Input : *pName -
  35. // Output : Returns true on success, false on failure.
  36. //-----------------------------------------------------------------------------
  37. bool ArgsExist( const char *pName )
  38. {
  39. int i;
  40. if ( pName && pName[0] == '-' )
  41. {
  42. for ( i = 0; i < g_ArgCount; i++ )
  43. {
  44. // Is this a switch?
  45. if ( g_Args[i][0] != '-' )
  46. continue;
  47. if ( !stricmp( pName, g_Args[i] ) )
  48. {
  49. return true;
  50. }
  51. }
  52. }
  53. return false;
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose: looks for the arg "pName" and returns it's parameter or pDefault otherwise
  57. // Input : *pName -
  58. // *pDefault -
  59. // Output : const char *
  60. //-----------------------------------------------------------------------------
  61. const char *ArgsGet( const char *pName, const char *pDefault )
  62. {
  63. int i;
  64. // don't bother with the last arg, it can't be a switch with a parameter
  65. for ( i = 0; i < g_ArgCount-1; i++ )
  66. {
  67. // Is this a switch?
  68. if ( g_Args[i][0] != '-' )
  69. continue;
  70. if ( !stricmp( pName, g_Args[i] ) )
  71. {
  72. // If the next arg is not a switch, return it
  73. if ( g_Args[i+1][0] != '-' )
  74. return g_Args[i+1];
  75. }
  76. }
  77. return pDefault;
  78. }
  79. void Error( const char *pString, ... )
  80. {
  81. va_list list;
  82. va_start( list, pString );
  83. vprintf( pString, list );
  84. printf("Usage: smtpmail -to <address(-es, ';' separated)> -from <address> -subject \"subject text\" [-verbose] [-server server.name] <FILENAME.TXT>\n" );
  85. exit( 1 );
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Purpose: simple routine to printf() all of the socket traffic for -verbose
  89. // Input : socket -
  90. // *pData -
  91. //-----------------------------------------------------------------------------
  92. void DumpSocket( HSOCKET, const char *pData )
  93. {
  94. printf( "%s", pData );
  95. fflush( stdout );
  96. }
  97. static char *months[] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
  98. //-----------------------------------------------------------------------------
  99. // Purpose: mail a text file using the SMTP mail server connected to socket
  100. // Input : socket -
  101. // *pFrom - from address
  102. // *pTo - to address
  103. // *pSubject - subject of the mail
  104. // *fp - text mode file opened
  105. //-----------------------------------------------------------------------------
  106. void MailSendFile( HSOCKET socket, const char *pFrom, const char *pTo[], const char *pSubject, FILE *fp )
  107. {
  108. int i;
  109. char buf[1024];
  110. SocketSendString( socket, "HELO\r\n" );
  111. SocketWait( socket, "\n" );
  112. sprintf( buf, "MAIL FROM: <%s>\r\n", pFrom );
  113. SocketSendString( socket, buf );
  114. SocketWait( socket, "\n" );
  115. for (i = 0; pTo[i] != NULL; i++)
  116. {
  117. sprintf( buf, "RCPT TO: <%s>\r\n", pTo[i] );
  118. SocketSendString( socket, buf );
  119. SocketWait( socket, "\n" );
  120. }
  121. SocketSendString( socket, "DATA\r\n" );
  122. SocketWait( socket, "\n" );
  123. time_t currentTime;
  124. time( &currentTime );
  125. struct tm *localTime = gmtime( &currentTime );
  126. sprintf( buf, "DATE: %02d %s %4d %02d:%02d:%02d\r\n", localTime->tm_mday, months[localTime->tm_mon], localTime->tm_year+1900,
  127. localTime->tm_hour, localTime->tm_min, localTime->tm_sec );
  128. SocketSendString( socket, buf );
  129. sprintf( buf, "FROM: %s\r\n", pFrom );
  130. SocketSendString( socket, buf );
  131. for (i = 0; pTo[i] != NULL; i++)
  132. {
  133. sprintf( buf, "TO: %s\r\n", pTo[i] );
  134. SocketSendString( socket, buf );
  135. }
  136. sprintf( buf, "SUBJECT: %s\r\n\r\n", pSubject );
  137. SocketSendString( socket, buf );
  138. while ( !feof( fp ) )
  139. {
  140. fgets( buf, 1024, fp );
  141. // A period on a line by itself would end the transmission
  142. if ( !strcmp( buf, ".\n" ) && !strcmp( buf, ".\r\n" ) )
  143. continue;
  144. SocketSendString( socket, buf );
  145. }
  146. SocketSendString( socket, "\r\n.\r\n" );
  147. SocketWait( socket, "\n" );
  148. }
  149. int main( int argc, char *argv[] )
  150. {
  151. ArgsInit( argc, argv );
  152. const char *pServerName = ArgsGet( "-server", "smtp1.valvesoftware.com" );
  153. const char *pTo[100];
  154. pTo[0] = ArgsGet( "-to", NULL );
  155. if ( !pTo[0] )
  156. {
  157. Error( "Must specify a recipient with -to <address(es)>\n" );
  158. }
  159. // split ; separated To string into an array of strings
  160. int c = 0;
  161. char *where;
  162. while (((where = (char *)strchr(pTo[c++],';')) != NULL) && c < 99)
  163. {
  164. *(where++) = '\0';
  165. pTo[c] = where;
  166. }
  167. pTo[c] = NULL;
  168. const char *pFrom = ArgsGet( "-from", NULL );
  169. if ( !pFrom )
  170. {
  171. Error( "Must specify a sender with -from <address>\n" );
  172. }
  173. const char *pSubject = ArgsGet( "-subject", "<NONE>" );
  174. int port = atoi( ArgsGet( "-port", "25" ) );
  175. const char *pFileName = argv[ argc-1 ];
  176. FILE *fp = fopen( pFileName, "r" );
  177. if ( !fp )
  178. {
  179. Error( "Can't open %s\n", pFileName );
  180. }
  181. SocketInit();
  182. // in verbose mode, printf all of the traffic
  183. if ( ArgsExist( "-verbose" ) )
  184. {
  185. SocketReport( DumpSocket );
  186. }
  187. HSOCKET socket = SocketOpen( pServerName, port );
  188. if ( socket )
  189. {
  190. SocketWait( socket, "\n" );
  191. MailSendFile( socket, pFrom, pTo, pSubject, fp );
  192. SocketSendString( socket, "quit\r\n" );
  193. SocketWait( socket, "\n" );
  194. SocketClose( socket );
  195. }
  196. else
  197. {
  198. printf("Can't open socket to %s:%d\n", pServerName, port );
  199. }
  200. fclose( fp );
  201. SocketExit();
  202. return 0;
  203. }