MS Access Forum / ActiveX Controls / February 2005
Coding the Winsock control....
|
|
Thread rating:  |
Brad Pears - 10 Nov 2004 17:02 GMT I have some sample code on connecting to a mail server using the winsock control to send an email automatically from an Access 2000 project...
However, I am not getting a connect request back from the mail server at all...There must be a missing step somewhere...
Does someone have some sample code they could send my way that will allow the client computer to connect to an SMTP server over port 25 and send an email?
The code I have seems to work but the .Connect request to the email server just sits there and never comes back. It seems as a connection is never established.
Here is the sample code....
(Form declaration code)
Option Compare Database Dim winsock1 As Winsock
(command button code)
Private Sub cmdSendMail_Click() Call SMTPSend("mydomain.com", "192.168.2.15", "bradp", "friggin", "This is the Subject", "This is the body")
End Sub
' Routine to send email
Sub SMTPSend(strMyDomain As String, _ strEmailServer As String, _ strEmailAddressWithoutDomain As String, _ strWhoToSayThisIsFrom As String, _ strSubject As String, _ strMessageBody As String) Set winsock1 = Me!axWinsockServer.Object winsock1.Protocol = sckTCPProtocol winsock1.RemoteHost = strEmailServer winsock1.RemotePort = 25 winsock1.Connect
' Wait for connection WaitForIt
Select Case Left$(strWSin, 3) Case "220" ' connected ok, send HELLO winsock1.SendData "HELO " & _ strMyDomain & _ vbCrLf WaitForIt winsock1.SendData "MAIL FROM: " & _ strWhoToSayThisIsFrom & _ vbCrLf WaitForIt winsock1.SendData "RCPT TO: " & _ strWhoToSayThisIsFrom & _ vbCrLf WaitForIt winsock1.SendData "DATA" & vbCrLf & _ "DATE:" & _ Format$(Now(), "mm/dd/yyyy hh:mm:ss") & _ "FROM: " & _ strWhoToSayThisIsFrom & vbCrLf & _ "TO:" & _ Format$(Now(), "mm/dd/yyyy hh:mm:ss") & _ "DATE:" & _ Format$(Now(), "mm/dd/yyyy hh:mm:ss") & _ "SUBJECT: " & _ strSubject & _ vbCrLf & _ strMessageBody & _ vbCrLf & _ "." & vbCrLf ' note: . & vbcrlf terminates the "send" WaitForIt ' parse and validate the return from the sever End Select ' tell the server you're done: winsock1.SendData "QUIT" & vbCrLf ' and that's it! winsock1.Close End Sub
Private Sub WaitForIt() WaitingforData = True While WaitingforData = True DoEvents Wend End Sub
' This should run when a connection has been established - but it never does....
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim Temp As String Temp = String(bytesTotal, " ") winsock1.GetData Temp, vbString Do If Right$(Temp, 1) = vbLf Then Temp = Left$(Temp, Len(Temp) - 1) End If Loop While Right$(Temp, 1) = vbLf strWSin = Temp WaitingforData = False End Sub
Any help with this would be greatly appreciated!!!
Thanks,
Brad
Ron Weiner - 10 Nov 2004 20:11 GMT Brad
If your clients are Win2K or later you might want to consider sending mail Via Microsoft CDO. Here is some sample code to get you started.
Public Sub testCDO() ' Purpose Send an Email with or without an attachment without using Outlook or other MAPI client ' Uses Late Binding - Does not need a reference to the Microsoft CDO For Windows library ' But the system CdoSys registered. CDOSys comes standard on Windows 2K and higher ' This code will likely fail on a Win 98 box
Const cdoSendUsingPort = 2 Const cdoBasic = 1 Dim objCDOConfig As Object, objCDOMessage As Object Dim strSch As String
strSch = "http://Schemas.microsoft.com/cdo/configuration/" Set objCDOConfig = CreateObject("CDO.Configuration") With objCDOConfig.Fields .Item(strSch & "sendusing") = cdoSendUsingPort .Item(strSch & "smtpserver") = "SomeSecureMailServer.SomeDomain.COM" 'Use only when SMTP server requires Authentication - Otherwise Rem out .Item(strSch & "SMTPAuthenticate") = cdoBasic .Item(strSch & "SendUserName") = "SomeName@SomeDomain.com" .Item(strSch & "SendPassword") = "YourPassword" .Update End With
Set objCDOMessage = CreateObject("CDO.Message") With objCDOMessage Set .Configuration = objCDOConfig .From = "Your Nice Name" .Sender = "You@YourDomain.com" .To = "Receiver@HerDomain.com" .Subject = "Sample CDO Message" '.TextBody = "This is a test for CDO.message" .HTMLBody = "This is a test for CDO.message. This is not Bold But <B>This is!</B>" '.AddAttachment "c:\Inv83595.pdf" '.MDNRequested = True .Send End With Set objCDOMessage = Nothing Set objCDOConfig = Nothing End Sub
I have found that this code to be reliable in my customers environment. Since it uses late binding there are no references to worry about, BUT you need to add error handler for cases where CDO is not available (Win 98), and when the mail server is not available, or authentication fails, or ... Well you get the idea.
Ron W
> I have some sample code on connecting to a mail server using the winsock > control to send an email automatically from an Access 2000 project... [quoted text clipped - 111 lines] > > Brad Brad Pears - 11 Nov 2004 17:24 GMT Great, I'll give that a shot... Except, we do have some Win98 clients as well...
CDO will not work for those clients?
> Brad > [quoted text clipped - 168 lines] > > > > Brad Alex Ivanov - 12 Nov 2004 03:46 GMT Are you sure your firewall is open on port 25? Try to telnet to your mail server on this port and see if you have a reply. A simple session may be like the following:
telnet mymail.myserver.com 25 220 mymail.myserver.com ESMTP helo alex@jigdo.com 250 mymail.myserver.com rcpt from: xxx@yyy.zzz 250 ok mail to: alex@myserver.com 250 ok data 354 go ahead that's all . 250 ok 1100230717 qp 33434 quit 221 mymail.myserver.com
 Signature Please reply to NG only. This email is not monitored. Alex.
> Brad > [quoted text clipped - 172 lines] >> >> Brad Brad Pears - 12 Nov 2004 20:09 GMT The firewall is allowing port 25 through because that's the port our Exchange server listens on...
In fact our Watchguard has a service specific to SMTP configured that allows data on port 25.
Thanks,
Brad
> Are you sure your firewall is open on port 25? > Try to telnet to your mail server on this port and see if you have a reply. [quoted text clipped - 192 lines] > >> > >> Brad Alex Ivanov - 13 Nov 2004 05:36 GMT This is a barebone code with no authentication and no encryption. Some mail servers may accept similar requests other not. My home ISP's mail server silently ignores the email sent this way though it seems that send succeeds. Our company's Exchange server is happy to work with it if the mail is sent to internal recipients. Anyway, you can try.
Private Sub Form_Load() With Winsock1 .RemoteHost = "mail.test.net" .RemotePort = 25 .Protocol = sckTCPProtocol .Connect End With End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Dim buf As String Dim retcode As Integer Static c250 As Integer Dim numOfRecipients numOfRecipients = 1 buf = Space(Winsock1.BytesReceived) Winsock1.GetData buf, vbString Debug.Print buf retcode = Val(buf) Select Case retcode Case 220 Winsock1.SendData "helo nothing.com" & vbCrLf c250 = 0 Case 250 If c250 < numOfRecipients Then Winsock1.SendData "mail to: test@test.net" & vbCrLf c250 = c250 + 1 ElseIf c250 = numOfRecipients Then Winsock1.SendData "rcpt from: nobody@nowhere.net" & vbCrLf c250 = c250 + 1 ElseIf c250 = numOfRecipients + 1 Then Winsock1.SendData "data" & vbCrLf c250 = c250 + 1 Else Winsock1.SendData "quit" & vbCrLf End If Case 354 Winsock1.SendData "Your data goes here." & vbCrLf & "." & vbCrLf Case 221 Winsock1.Close MsgBox "Mail Sent" End Select End Sub
 Signature Please reply to NG only. This email is not monitored. Alex.
> The firewall is allowing port 25 through because that's the port our > Exchange server listens on... [quoted text clipped - 216 lines] >> >> >> >> Brad Alex Ivanov - 13 Nov 2004 06:21 GMT I accidentally swithced "from" and "to" this caused rejection from my isp. This is the corrected code that works. If you need to send the mail to external clients, you will need either to add an authentication code or set the RemoteHost property to their mail servers before sending (unless you have an 'open proxy' allowing mail forwarding).
HTH
Option Explicit
Private Sub Form_Load() With Winsock1 .RemoteHost = "test.net" .RemotePort = 25 .Protocol = sckTCPProtocol .Connect End With End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Dim buf As String Dim retcode As Integer Static c250 As Integer Dim numOfRecipients numOfRecipients = 1 buf = Space(Winsock1.BytesReceived) Winsock1.GetData buf, vbString Debug.Print buf retcode = Val(Left(buf, 3)) Select Case retcode Case 220 Winsock1.SendData "helo nothing.com" & vbCrLf c250 = 0 Case 250 If c250 = 0 Then Winsock1.SendData "mail from: test@test" & vbCrLf c250 = c250 + 1 ElseIf c250 < numOfRecipients + 1 Then Winsock1.SendData "rcpt to: consul@test.net" & vbCrLf c250 = c250 + 1 ElseIf c250 = numOfRecipients + 1 Then Winsock1.SendData "data" & vbCrLf c250 = c250 + 1 Else Winsock1.SendData "quit" & vbCrLf End If Case 354 Winsock1.SendData "Subject: My Subject" & vbCrLf _ & "From: Me" & vbCrLf & vbCrLf _ & "Your data goes here." & vbCrLf & "." & vbCrLf Case 221 Winsock1.Close MsgBox "Mail Sent" End Select End Sub
 Signature Please reply to NG only. This email is not monitored. Alex.
> This is a barebone code with no authentication and no encryption. Some > mail servers may accept similar requests other not. > My home ISP's mail server silently ignores the email sent this way though > it seems that send succeeds. Our company's Exchange server is happy to > work with it if the mail is sent to internal recipients. Anyway, you can > try. Brad Pears - 22 Nov 2004 21:54 GMT So to test this, do I just add the Microsoft Winsock control to my form and rename the winsock control to "winsock1"?? When I add the control it's named something completely different... Should I be worried about that?
Not sure how to test this...
Thanks,
Brad
> I accidentally swithced "from" and "to" this caused rejection from my isp. > This is the corrected code that works. [quoted text clipped - 59 lines] > > work with it if the mail is sent to internal recipients. Anyway, you can > > try. ?zt?rk - 13 Jan 2005 22:04 GMT "Brad Pears" <donotreply@notreal.com>, haber iletisinde ?unlar? yazd?:OnbkG4N0EHA.3588@TK2MSFTNGP14.phx.gbl...
> So to test this, do I just add the Microsoft Winsock control to my form and > rename the winsock control to "winsock1"?? When I add the control it's [quoted text clipped - 73 lines] > > > work with it if the mail is sent to internal recipients. Anyway, you can > > > try. Brad Pears - 22 Nov 2004 21:58 GMT So to test this, do I just add the ActiveX Microsoft Winsock version 6 control to my form and rename the winsock control to "winsock1"?? When I add the control it's named something completely different... (ActiveXctl1)
Should I be worried about that?
Not sure how to test this...
Thanks,
Brad
> I accidentally swithced "from" and "to" this caused rejection from my isp. > This is the corrected code that works. [quoted text clipped - 59 lines] > > work with it if the mail is sent to internal recipients. Anyway, you can > > try. Alex Ivanov - 23 Nov 2004 04:36 GMT Yes, that basically all. Yo will need to set RemoteHost property to your mail server address and make sure the "rcpt to:" line contains a valid email address recognized by that server otherwise you may need to implement an authentication protocol.
 Signature Please reply to NG only. This email is not monitored. Alex.
> So to test this, do I just add the ActiveX Microsoft Winsock version 6 > control to my form and [quoted text clipped - 75 lines] >> > can >> > try. Brad Pears - 23 Nov 2004 17:40 GMT I am having a heck of a time with this - implementing it into my project... I was able to get it to work standalone by having all the code on the same screen where I inserted the winsock control... But I cannot seem to get it to work properly when the code to send the mail is in a procedure in a module...
Here's the scoop...
On one of my forms, I added the Winsock control and renamed it to Winsock1.
However, it's not actually on this form where I have placed the code to send the email. Instead - I placed the code inside a procedure that exists in a module. When the user clicks a command button on this form, it runs the on-click event which in turn calls a "SendMail" procedure to do the job.
So, in my module, in the declarations section, I have declared ...
public winsock1 as winsock.
Then I have my called procedure as follows...
Public Sub SendMail()
With Winsock1 .RemoteHost = "true3" .RemotePort = 25 .Protocol = sckTCPProtocol .Connect End With
End Sub
Then in this same module I have placed the other code to actually send the email (shown below...)
The problem is that when the procedure is called to connect to my mail server I get the following error everytime ...
"Object variable or with block variable not set" and when I click the Debug button, the code that is highlited is the .remotehost = "true3" line.
What am I missing? Is my winsock control not being defined properly somewhere?
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Dim buf As String Dim retcode As Integer 'Dim strMailTO As String 'Dim strMailSubject As String 'Dim strBody As String Static c250 As Integer Dim numOfRecipients numOfRecipients = 1 buf = Space(Winsock2.BytesReceived) Winsock2.GetData buf, vbString Debug.Print buf retcode = Val(Left(buf, 3)) Select Case retcode Case 220 Winsock2.SendData "helo truenorthloghomes.com" & vbCrLf c250 = 0 Case 250 If c250 = 0 Then ' winsock1.SendData getMailFrom(CurrentUser()) & vbCrLf c250 = c250 + 1 ElseIf c250 < numOfRecipients + 1 Then ' winsock1.SendData "rcpt to: craigd" & vbCrLf c250 = c250 + 1 ElseIf c250 = numOfRecipients + 1 Then Winsock1.SendData "data" & vbCrLf c250 = c250 + 1 Else Winsock1.SendData "quit" & vbCrLf End If Case 354 Winsock1.SendData "Subject: " & strSubject & vbCrLf _ & "From: " & getMailFromFullName(CurrentUser()) & vbCrLf & vbCrLf _ & strBody & vbCrLf & "." & vbCrLf Case 221 Winsock1.Close MsgBox "Mail message successfully sent to " & strTo End Select
End Sub
> Yes, that basically all. Yo will need to set RemoteHost property to your > mail server address and make sure the "rcpt to:" line contains a valid email [quoted text clipped - 80 lines] > >> > can > >> > try. Alex Dybenko - 23 Nov 2004 19:38 GMT Brad, in order to use Winsock control without form - you have to create new instance, but this is posible in VB only, because you have to add license. this is not possible in Access. so in access you have to insert in a form in order to have it instance created. form can be hidden, if you dont want to show it HTH
 Signature Alex Dybenko (MVP) http://Alex.Dybenko.com http://www.PointLtd.com
>I am having a heck of a time with this - implementing it into my project... > I was able to get it to work standalone by having all the code on the same [quoted text clipped - 173 lines] >> >> > can >> >> > try. Brad Pears - 23 Nov 2004 21:01 GMT I was able to get this working but I have found that I will sometimes get an error...
Runtime Error: 40006 "Wrong protocol or connection state for the requested transaction or request"
on the "Winsock1.GetData buf, vbString" line in the winsock1_DataArrival event.
If I try to send a couple of emails back to back. Each time an email is sent, there is code that closes the connection - but it appears that maybe it is not being closed properly??
Have you seen this before and do you have any ideas on how to proceed? Obviously this will not work in it's current state.
Thanks,
Brad
> Brad, > in order to use Winsock control without form - you have to create new [quoted text clipped - 19 lines] > > module. When the user clicks a command button on this form, it runs the > > on-click event which in turn calls a "SendMail" procedure to do the job.
> > So, in my module, in the declarations section, I have declared ... > > [quoted text clipped - 156 lines] > >> >> > can > >> >> > try. Alex Ivanov - 24 Nov 2004 04:51 GMT Perhaps what you're experience is due to the race of signals. You may try to add a static boolean variable to the procedure and set it to true when your mailer starts and false when it finishes. Then check this var upon entering the code and if previous send command is still running raise an error or do something else to prevent the race condition. And, yes, clear the c250 variable in case 221 - it is static also.
HTH
 Signature Please reply to NG only. This email is not monitored. Alex.
>I was able to get this working but I have found that I will sometimes get >an [quoted text clipped - 224 lines] >> >> >> > can >> >> >> > try. Brad Pears - 24 Nov 2004 19:38 GMT What exactly do you mean by a race of signals?
Also what exactly does declaring a variable of static enable vs declaring it as public?
> Perhaps what you're experience is due to the race of signals. You may try to > add a static boolean variable to the procedure and set it to true when your [quoted text clipped - 233 lines] > >> >> >> > can > >> >> >> > try. Alex Ivanov - 24 Nov 2004 21:12 GMT Winsock operates asynchronously, that meens if you have a code similar to this
sendmail "somebody", "something" sendmail "somebody else", "something else"
at the time you are calling the sendmail second time, the first sendmail request is still in process. To workaround of this problem you can make your sendmail function synchronous, that does not return until the mail is sent. In the example I used the form_load event to send the mail but let us create a dedicated function to do that:
Private running as boolean ' at module scope Private anError as boolean
Private Function SendMailad(sendTo as string, message as string) as boolean running=true With Winsock1 .RemoteHost = "mail.test.net" .RemotePort = 25 .Protocol = sckTCPProtocol .Connect End With while running 'wait until running=false doevents 'add also a time cheking code here to prevent an infinite loop wend if not anError then sendmail=true else sendmail=false End Function
'excerpt from DataArrival '... Case 221 Winsock1.Close MsgBox "Mail Sent" c250=0 'reset the counter running=false Case Else ' unexpected here, treating like error Winsock1.Close running=false c250=0 anError=true End Select
The reason c250 is static is that it needs to retain its value between function calls. You might move it outside of DataArrival which would have the same effect, but then it would be accessible to other procedures within the same module, which would not make sense.
 Signature Please reply to NG only. This email is not monitored. Alex.
> What exactly do you mean by a race of signals? > [quoted text clipped - 268 lines] >> >> >> >> > can >> >> >> >> > try. Brad Pears - 25 Nov 2004 16:05 GMT Got ya.. yes I think this is what is happening....
Thanks... I'll let you know if I have more problems!!
> Winsock operates asynchronously, that meens if you have a code similar to > this [quoted text clipped - 319 lines] > >> >> >> >> > can > >> >> >> >> > try. Brad Pears - 23 Nov 2004 13:35 GMT I am able to communicate with my mail server on port 25. However, how do you end the DATA command???
In the Telnet session after I type in "Data test", I get a response back saying... 354 Start mail input; end with <CRLF>.<CRLF>
After I type in the body of the message, I cannot end that line. I've tried typing in exactly what it says and various other things but none seem to work.
We are using an Exchange 2000 server.
Any ideas??
Thanks,
Brad
My FTP client is saying to end with
> I accidentally swithced "from" and "to" this caused rejection from my isp. > This is the corrected code that works. [quoted text clipped - 59 lines] > > work with it if the mail is sent to internal recipients. Anyway, you can > > try. stefan hoffmann - 23 Nov 2004 14:00 GMT hi Brad,
> 354 Start mail input; end with <CRLF>.<CRLF> > After I type in the body of the message, I cannot end that line. I've tried > typing in exactly what it says and various other things but none seem to > work. >> vbCrLf & "." & vbCrLf = Chr(13) & Chr(10) & "." Chr(13) & Chr(10)
mfG --> stefan <--
Brad Pears - 23 Nov 2004 17:59 GMT Thanks for that!
> hi Brad, > [quoted text clipped - 7 lines] > mfG > --> stefan <-- Brad Pears - 23 Nov 2004 20:33 GMT I was able to get this working but I have found that I will sometimes get an error...
Runtime Error: 40006 "Wrong protocol or connection state for the requested transaction or request"
on the "Winsock1.GetData buf, vbString" line in the winsock1_DataArrival event.
If I try to send a couple of emails back to back. Each time an email is sent, there is code that closes the connection - but it appears that maybe it is not being closed properly??
Have you seen this before and do you have any ideas on how to proceed? Obviously this will not work in it's current state.
Thanks,
Brad
> hi Brad, > [quoted text clipped - 7 lines] > mfG > --> stefan <-- Mangi - 01 Feb 2005 20:41 GMT Hi, I would like to do the same thing using VB .Net. Is there an alternative to using winsock in .Net? Maybe a simpler way of creating a VB .Net mail application that would do the same thing without the winsock DataArrival.
Thanks,
Mangi.
> Brad > [quoted text clipped - 168 lines] > > > > Brad Alex Ivanov - 02 Feb 2005 20:08 GMT Try this
Dim email As New System.Web.Mail.MailMessage() email.To = "RecipientAddress" email.From = "SenderAddress" email.Body = "MessageText" email.Subject = "SubjectText" email.BodyFormat = Web.Mail.MailFormat.Text System.Web.Mail.SmtpMail.SmtpServer = "SmtpServerName" System.Web.Mail.SmtpMail.Send(email)
 Signature Please reply to NG only. This email is not monitored. Alex.
> Hi, > I would like to do the same thing using VB .Net. [quoted text clipped - 192 lines] >> > >> > Brad
|
|
|