PDA

Ver la versión completa : ayuda smtp con VB



dbianx
14-11-2004, 22:45
Hola a todos , tengo un problema con este codigo que e escrito para enviar email , como veis es un codigo muy sencillo que funciona bien asta la segunda espera en concreto el "250" del servidor , ademas el bucle de la funcion espera deja mucho que desear pero digamos que estoy atascado , tambien decir que e probado a conectar via telenet con el servidor que use para probarlo y funciona perfectamente con los parametros que le doy de direcciones etc ...
eso solo que no llego a recivir la respuesta , no se por que causa es esto ya que en la respuesta del connect capto perfectamente el "220" usando la misma funcion de espera, aunque intuyo que tendra algo que ver con la funcion espera .... e sniffeado la conexion con ethereal los dos ultimos registros son el "helo servidor.com" que envia el programa y el ultimo un TCP ACK del servidor , aahi se acaba , bueno gracias a todos por gastar su timepo leyendo .


Dim cotenidolog As String
Dim respuesta As String

Private Sub Form_Load()
Winsock1.Connect
espera ("220")
Winsock1.SendData ("helo servidor.com" + CvbCrLf)
espera ("250")
Winsock1.SendData ("mail from:" + "<[email protected]>" + vbCrLf)
espera ("250")
Winsock1.SendData ("rcpt to:" + "" + Chr(13))
espera ("250")
Winsock1.SendData ("data" + Chr(13))
espera ("354")
Winsock1.SendData ("." + Chr(13))
espera ("250")
Winsock1.SendData ("quit" + Chr(13))


End Sub

Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
Winsock1.Close
Winsock1.Accept requestID
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Winsock1.GetData respuesta
MsgBox (respuesta + "------getdata")
'Text1.Text = Text1.Text + respuesta
End Sub

Private Sub Winsock1_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
MsgBox ("winsock error")


End Sub

'Public Function espera(codigorespuesta As String)
'Do Until Left(respuesta, 3) = codigorespuesta
'DoEvents
'Loop
'MsgBox (respuesta)
'respuesta = ""
'codigorespuesta = ""
'End Function
Public Function espera(codigorespuesta As String)
Do Until Left(respuesta, 3) = codigorespuesta
DoEvents
Loop
If codigorespuesta = Left(respuesta, 3) Then
MsgBox (respuesta)
Else: MsgBox (codigorespuesta)
End If
respuesta = ""
End Function

diarrea
16-11-2004, 17:26
Ouch toy confundioo... vamos a ver... creo que el código se simplifica mucho si tienes en cuenta los eventos del winsock. Cuando el winsock se conecta al server smtp se desencadenará el evento winsock_connect y a la vez se recibe el código 220. En caso contrario, correrá el evento winsock_error con su correspondiente código de error.
Lo más simple quedaría así:


Public Sub ConectarYA()
ws.sckTCPProtocol
ws.RemotePort=25
ws.RemoteHost="smpt.servidor.es"
ws.Connect
End Sub



Una vez que hayas establecido la conexión:
ws.SendData y todo lo que sigue ("from", "rcpt to", "data", ".")
Después del envío de cada comando (from, rcpt...) deberías de recibir el winsock_SendComplete y con winsock_DataArrival recogerías la respuesta del server.

dbianx
17-11-2004, 23:43
Gracias por responder Diarrea ,

Quote:
Public Sub ConectarYA()
ws.sckTCPProtocol
ws.RemotePort=25
ws.RemoteHost="smpt.servidor.es"
ws.Connect
End Sub

os parametros de la conexion que me comentas aunque no estan escritos en el codigo si que lo estan denrto de la ventana propiedades del control winsock (remotehost y remoteport sin olvidar tcp como porotocolo)

Quote:
Una vez que hayas establecido la conexión:
ws.SendData y todo lo que sigue ("from", "rcpt to", "data", ".")
Después del envío de cada comando (from, rcpt...) deberías de recibir el winsock_SendComplete y con winsock_DataArrival recogerías la respuesta del server.

El procedimiento que aqui describes es exactamente lo que esta escrito en el codigo a excepcion de que no tiene codigo a ejecutar en el evento sendcomplete (no es necesario)

En fin muchas gracias por responder pero mi programa por alguna razon desconocida sigue sin funcionar seguire investigando y si alguien tiene algo que aportarestare encantado de leerlo gracias a todos por su tiempo.

NeoGenessis
20-11-2004, 21:29
si te soy sincero no me he mirado el codigo al 100%, ya k creo k diarrea te ha dado una excelente respuesta. de todos modos me llama la atencion la linea:

Winsock1.SendData ("helo servidor.com" + CvbCrLf)

CvbCrLF, no lo habia visto nunca. Te lo digo por que viendo lo que pones fijo que has usado copiar y pegar.

diarrea
21-11-2004, 00:17
Es verdad---> vbCrLf.

dbianx
22-11-2004, 19:18
MMMM otra vez mil gracias por responder , y como brevemente conrtesto DIARREA
vbCrLf = chr(13) osea INTRO
Y no el codigo no es copy + paste sino creo que no me estaria dando problemas , jejejej bueno aun asi yo sigo en mis ratos libres con este codigo si consigo dar con la respuesta la cuelgo para que puedan verla , tambien entiendo que a la gente que pasa por aki no le apetece ponerse a "depurar" un codigo que no es suyo y que seguramente tienen algo parecido para hacer esto , asi con todo mil gracias a todos .....

dbianx
22-11-2004, 19:21
Ostias colega que rapido lei por que no estoy en casita que tengo todo mi codigo lo comprobare en cuanto llegue , ostias espero que solo sea esoooooooooo un puto error sintactico , bueno cuando llegue les cuento si funciono gracias ...

dbianx
20-12-2004, 15:50
Bueno pues ya que nadie "quiso/fue capaz" y al final yo lo consegui lo pasteo para el que le interese este funciona 100 % , para los mas negativos esta programado por mi al 100 % lo que para muchos no sera un merito pero para mi si y me enorgullezco de haberlo conseguido ademas de brindarselo a cualquiera que lo necesite ...... (esto solo era el modulo de envio por smtp para el programa final que estoy escribiendo al acabar este me surgen nuevas dudas de programacion que yo mismo expongo dentro del foro programacion gracias)

Dim recibido As String

Private Sub Command1_Click()
MsgBox (recibido)
End Sub

Private Sub Form_Load()
Winsock1.RemotePort = 25
Winsock1.RemoteHost = "servidor.com"
Winsock1.Connect
espera ("220")
Winsock1.SendData ("helo servidor.com" & vbCrLf)
espera ("250")
Winsock1.SendData ("mail from:<[email protected]>" & vbCrLf)
espera ("250")
Winsock1.SendData ("rcpt to:<[email protected]>" & vbCrLf)
espera ("250")
Winsock1.SendData ("data" & vbCrLf)
espera ("354")
Winsock1.SendData ("contenido email" & vbCrLf & "." & vbCrLf)
espera ("250")
Winsock1.SendData ("quit" & vbCrLf)

End Sub





Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
Winsock1.Close
Winsock1.Accept requestID
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Winsock1.GetData recibido
Text1.Text = Text1.Text & recibido

End Sub

Private Sub Winsock1_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
MsgBox ("winsock_error" & Description)
End Sub



Public Function espera(codigorespuesta As String)
Do Until codigorespuesta = Left(recibido, 3)
DoEvents
Loop
recibido = ""
MsgBox ("respondido con " & codigorespuesta)
'MsgBox (codigorespuesta & " comparar " & Left(3, recibido))

'Do
'Loop Until codigorespuesta <> Left(3, recibido)
'recibido = ""
End Function

NeoGenessis
23-12-2004, 22:47
de hecho vbCrLf = chr$(13)chr$(10), es decir enter mas salto de linea.
ese es el problema al leer archivos unix, k solo usan uno de los dos simbolos.

Tienes razon en cuanto a lo depurar el codigo de otro, de todos modos debes plantearte una cosa. estas haciendo programacion estructurada, eso significa dividir el codigo en unidades logicas, y aprovechar las funciones propias de los controles. una forma de aprovechar la funcion k recibe los datos para comprobar todas las respuestas del server es usando una variable de estado. En otras palabras un flag.

Es decir k cuando envies el saludo pones el flag a 1 (p ej) y al recivir la respuesta compruebas el flag para saber si era lo k esperabas. En el sigiente paso el flag a 2, y asi.

dbianx
24-12-2004, 12:57
mmmm , que bueno , al principio estuve intentando hacer algo de este tipo , claro ni siquiera sabian q a esto se le llama "flag", lo q paso es q no consegui hacerlo funcionar de primeras y rapidamente pase a intentar evaluar las respuestas del servidor con una funcion que contuviese un sencillisimo bucle q evaluase los 3 primeros caracteres y los comparase con lo que debia recibir , el bucle debia comntener la funcion doevents para dejar seguir esperando eventos en este caso el mas imporetante era el dataarrival del winsock para que llegase la respuesta del server,al final parece que funciona como modulo independiente , pero me intriga que no lo aga en cuanto lo una a otro programa que este tambien funcionando con un bucle que compruebe la funcion de API getasynckeystate (¿os imaginais para que sera?) aunque en teoria usando bien el doevents deberia funcionar , pero tambien con tu respuesta Neogenessis me as echo volver a pensar que quizas mi programa funcionaria mejor usando flags dentro del evento dataarrival del winsock por que mientras espero la respuesta del server que dependiendo de la red en que estuviese el ordenador que ejecutase el programa y podria ser mas larga no estaria calculando el bucle de esperar respuesta y todo el programa que tambien estaria ejecutando funciones del tipo getasynckeystate y grabando archivos etc .... no se veria temporalmente pausada y no tendria esa pequeña fuga de informacion , bueno espero haberme explicado bien , en cuanto vaya sabiendo mas cosas de este tema las ire comentando , por supuesto agradecere cualquier comentario como los que habeis echo y tanto me han ayudado directa o indirectamente , gracias a todos y un saludo

N4nd0
31-12-2004, 02:39
Saludos...

no dudo que las respuestas esten correctas, no he provado tu codigo pero tengo una duda...tu pones:

Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
Winsock1.Close
Winsock1.Accept requestID
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Winsock1.GetData recibido
Text1.Text = Text1.Text & recibido

End Sub

te explico...repito no he provado tu codigo pero en estas lineas:
Winsock1.Close
Winsock1.Accept requestID

¿porque cierras el winsock y luego aceptas la conexion?
¿no deberias primero recivir la conexion y luego cerrarla?

vuelvo a repetir NO he provado el codigo solo fue un rapido vistazo...

dbianx
04-01-2005, 07:54
bueno pos esto biene de que es la forma en q aprendi q ay q hacerlo , la verdad q lo poco que se de winsock en visual basic lo saque al principio de textos como este
http://www.elguruprogramador.com.ar/zonas/ver.asp?cod=63
en donde pone esto
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim datos As String
Winsock1.GetData datos
Text1.Text = Text1.Text + datos
End Sub

Datos queda transformada en una variable de cadena, y WinSock almacena los datos que recibe del Cliente en el buffer y luego ingresan a la variable datos, dicha variable mostrará su contenido en el control TextBox (Text1).

En el evento ConnectionRequest...

Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
Winsock1.Close
Winsock1.Accept requestID
End Sub

Este evento es muy importante, permite aceptar la petición de conexión. Sin este evento el resto del programa no tendría efecto.

claro q el agregar lo recibido a un text box es opcional , pero si es bueno muchas veces para seguir un control de lo recibido y comprobar q esta ok o ver donde falla , en algun otro lado explicaban que sin este codigo (winsock1.accept requestID) dentro del evento connection request no podia aceptar la conexion y lo de cerrar es por si acaso no quedi bien cerrado el socket para q no diese un error , la verdad que siempre lo e echo asi y me a funcionado bien , vamos q cuando mis programas han fallado no a sido en ese punto , claro q en realidad no se si esto es realmente lo mejor pero de momento funciona y acepto cualquier sugerencia q pueda ser mas beneficiosa para mi programa .
Personalmente despues de haber investigado esto y haber habaldo con gente q sabe mas del tema q yo (programadores profesionales y no aficionados como yo) el tema parece ser excluyendo fallos corrientes de mi programa la concurrencia dentro de un mismo programa , gente me dice q este lenguaj quizas no sea el apropiado pero yo se q ay gente q a echo cosas de estas con VB , no digo q sea lo mejor .......

decir tambien q el codigo funciona pero es tan simple q tiene q funcionar en un entorno perfecto que no haya ningun fallo , por ejmplo una respuesta de error como un rcpt no admitido o cualquier otra cosa , osea q primero tengo q asegurarme q con el servidor smtp los parametros q le pase me deje hacer la transaccion por q sino se quedara pillado

En resumidas cuentas no es un programa funcinal pero sirve muy bien de experiencia
gracias todos , un saludo.