Ir al contenido


Foto

Enviar email sin componentes. Protocolo SMTP


  • Por favor identifícate para responder
4 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 25 noviembre 2010 - 02:03

Para el envío de correo electrónico disponemos de herramientas y componentes muy buenos, pero hacen que nuestro código dependa de ellos y de la VCL.

Para enviar un email por código, sin el uso de componentes y con el protocolo SMTP no extendido, podemos usar un código similar al que propongo.

Aclarar que no todos los servidores nos van a servir pues casi todos nos piden una clave. En el caso de que tengamos cuenta de Yahoo, nos va a funcionar perfectamente.

El nombre de usuario y password tenemos que enviarlos codificados en BASE64, el resto va en texto llano.

El código está bastante comentado para comprender bien el protocolo, que incluso nos puede permitir camuflar el remitente.  *-)



delphi
  1. const
  2.   CRYPT_STRING_BASE64 = 1;
  3.  
  4. function CryptBinaryToString(pbBinary: PByte; cbBinary: DWORD; dwFlags: DWORD;
  5.   pszString: PChar; var pcchString: DWORD): BOOL; stdcall;
  6.   external 'Crypt32.dll' name 'CryptBinaryToStringA';
  7.  
  8. function CryptStringToBinary(pszString: PChar; cchString: DWORD; dwFlags: DWORD;
  9.   pbBinary: PByte; var pcbBinary: DWORD; pdwSkip: PDWORD;
  10.   pdwFlags: PDWORD): BOOL; stdcall;
  11.   external 'Crypt32.dll' name 'CryptStringToBinaryA';
  12.  
  13. function Base64Encode(S: String): String;
  14. var
  15.   Size: DWORD;
  16. begin
  17.   if CryptBinaryToString(@S[1], Length(S), CRYPT_STRING_BASE64 ,nil, Size) then
  18.   begin
  19.     SetLength(Result, Size-1);
  20.     if not CryptBinaryToString(@S[1], Length(S), CRYPT_STRING_BASE64, PChar(Result), Size) then
  21.       Result:= EmptyStr;
  22.   end;
  23. end;
  24.  
  25. function SendMail(_From, _To, _SMTP, User, Password, _Subject, _Message: String): boolean;
  26. var
  27.   WSA:          TWSADATA;
  28.   iProtocolPort: integer;
  29.   sBuffer:      ShortString;
  30.   hServer:      TSOCKET;
  31.   lpHostEntry:  PHOSTENT;
  32.   lpServEntry:  PSERVENT ;
  33.   SockAddr:      SOCKADDR_IN ;
  34. begin
  35.   Result:= false;
  36.   iProtocolPort := 0;
  37.   if(WSAStartup(MakeWord(1,1), WSA) <> 0) then exit;
  38.  
  39.   // Obtenemos la dirección del servidor SMTP
  40.   lpHostEntry:= gethostbyname(PCHAR(_SMTP));
  41.   if(lpHostEntry <> nil) then
  42.   begin
  43.     // Creamos el socket TCP/IP
  44.     hServer:= socket(PF_INET, SOCK_STREAM, 0);
  45.     if(hServer <> INVALID_SOCKET) then
  46.     begin
  47.       // Obtenemos el puerto del servicio de correo:
  48.       lpServEntry:= getservbyname('mail', 0);
  49.       // si no está especificado usamos el puerto por defecto
  50.       if lpServEntry = nil then
  51.         iProtocolPort:= htons(IPPORT_SMTP)
  52.       else
  53.         iProtocolPort:= lpServEntry.s_port;
  54.  
  55.       // Configuramos la estructura Socket Address para conectar
  56.       SockAddr.sin_family:= AF_INET;
  57.       SockAddr.sin_port:= iProtocolPort;
  58.       SockAddr.sin_addr:= (PInAddr(lpHostEntry.h_addr_list^))^;
  59.       // Y conectamos el Socket
  60.       if connect(hServer, SockAddr, sizeof(SockAddr))= 0 then
  61.       begin
  62.         // Recibimos la respuesta de inicio desde el SMTP
  63.         recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  64.         if Pos('220', sBuffer) = 1 then  // Ok al conectar
  65.         begin
  66.           // Enviamos HELO
  67.           sBuffer:= 'HELO ' + _SMTP + #13 + #10;
  68.           send(hServer, sBuffer[1], Length(sBuffer), 0);
  69.           recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  70.  
  71.           // Enviamos "rset"
  72.           sBuffer:= 'rset'+#13+#10;
  73.           send(hServer, sBuffer[1], Length(sBuffer), 0);
  74.           recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  75.  
  76.           // Loging
  77.           sBuffer:= 'auth LOGIN'+#13+#10;
  78.           send(hServer, sBuffer[1], Length(sBuffer), 0);
  79.           recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  80.           if Pos('334', sBuffer) = 1 then  //No error en comando auth LOGIN
  81.           begin
  82.             sBuffer:= Base64Encode(User);
  83.             send(hServer, sBuffer[1], Length(sBuffer), 0);
  84.             recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  85.             if Pos('334', sBuffer) = 1 then // Ok LOGIN USER
  86.             begin
  87.               sBuffer:= Base64Encode(Password);
  88.               send(hServer, sBuffer[1], Length(sBuffer), 0);
  89.               recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  90.               if Pos('235', sBuffer) = 1 then  // Ok LOGIN PASSWORD
  91.               begin
  92.                 // Enviamos origen: MAIL FROM:<MyCuenta@dominio.com>
  93.                 sBuffer:= 'MAIL FROM:<'+_From+'>' +#13+#10;
  94.                 send(hServer, sBuffer[1], Length(sBuffer), 0);
  95.                 recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  96.  
  97.                 // Enviamos destino RCPT TO:<Destinop@dominio.com>
  98.                 // podemos repetir para mas destinos
  99.                 sBuffer:= 'RCPT TO:<'+_To+'>' +#13+#10;
  100.                 send(hServer, sBuffer[1], Length(sBuffer), 0);
  101.                 recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  102.  
  103.                 // Enviamos DATA
  104.                 sBuffer:= 'DATA'+#13+#10;
  105.                 send(hServer, sBuffer[1], Length(sBuffer), 0);
  106.                 recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  107.                 if pos('354', sBuffer) = 1 then // Ok en comando DATA
  108.  
  109.                 // Enviamos la cabecera del mensaje
  110.                 sBuffer:= 'Subject: '+ _Subject +#13+#10;
  111.                 send(hServer, sBuffer[1], Length(sBuffer), 0);
  112.                 sBuffer:= 'To: '+_To +#13+#10;
  113.                 send(hServer, sBuffer[1], Length(sBuffer), 0);
  114.                 sBuffer:= 'From: '+_From +#13+#10;
  115.                 send(hServer, sBuffer[1], Length(sBuffer), 0);
  116.  
  117.                 // Enviamos el cuerpo del mensaje
  118.                 send(hServer, _Message[1], Length(_Message), 0);
  119.  
  120.                 // Enviamos fin de trasmisión
  121.                 sBuffer:= #13+#10+'.'+#13+#10;
  122.                 send(hServer, sBuffer[1], Length(sBuffer), 0);
  123.                 recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  124.                 if Pos('250', sBuffer) = 1 then // Ok en el envío del Mensaje
  125.                 begin
  126.                   // Enviamos QUIT
  127.                   sBuffer:= 'QUIT'+#13+#10;
  128.                   send(hServer, sBuffer[1], Length(sBuffer), 0);
  129.                   recv(hServer, sBuffer[1], sizeof(sBuffer), 0);
  130.                   if Pos('221', sBuffer) = 1 then // Ok en QUIT
  131.                     Result:= true;
  132.                 end;
  133.               end;
  134.             end;
  135.           end;
  136.         end;
  137.       end;
  138.       // Cerramos el Socket
  139.       closesocket(hServer);
  140.     end;
  141.   end;
  142.   WSACleanup();
  143. end;




Un ejemplo de uso:



delphi
  1.   SendMail('MiCuenta@yahoo.es', 'Destino@gmail.com', 'smtp.correo.yahoo.es',
  2.           'Usuario', 'Password',
  3.           'Prueba', '¿Hola como estás?, ¡¡esto funciona correctamente!!');




Es un código experimental pero que puede servir de base de desarollo.

Espero que sea de utilidad.

Saludos.
  • 0

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 25 noviembre 2010 - 02:36

Ya lo probamos amigo, como siempre, muy buen código (y)

Salud OS
  • 0

#3 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 25 noviembre 2010 - 03:21

Esta muy bueno el asunto, ¿que tan seguro es?... digo *-)


Saludos!
  • 0

#4 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 26 noviembre 2010 - 04:52

Esta muy bueno el asunto, ¿que tan seguro es?... digo *-)


Si te refieres a ir de incógnito, he de aclarar que aunque puedes camuflar tu dirección de correo, no lo he implementado ni creo que se deba exponer públicamente.  ;)

Saludos.
  • 0

#5 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 26 noviembre 2010 - 07:36


Esta muy bueno el asunto, ¿que tan seguro es?... digo *-)


Si te refieres a ir de incógnito, he de aclarar que aunque puedes camuflar tu dirección de correo, no lo he implementado ni creo que se deba exponer públicamente.  ;)

Saludos.


Bien, eso se entiende.
Yo lo decía más que todo en cuanto a la seguridad del mensaje en sí, pero creo que la duda no viene al caso, ya es cosa del SMTP ;)



Saludos!
  • 0




IP.Board spam blocked by CleanTalk.