Thursday, July 29, 2004

Disabling and Enabling POP3 and IMAP protocol settings via ADSI

  When you install Exchange and create all your mailboxes by default every mailbox will have POP3,IMAP and HTTP protocols enabled. Good practice is if you don't want people to use these protocols is just disable the protocols on the server which makes the user account settings redundant. But this is not always possible and sometimes you need to leave POP3 and IMAP access enabled for some applications or clients. So to stop people using POP3 and IMAP it can be a good idea to disable that protocol on their Active Directory user account.

  To do this via ADSI is not that hard if you keep the following things in mind. The property that controls both these setting is the protocolSettings attribute of the User object. This is a mutli-valued property which also holds the setting for HTTP (OWA Access) as well.  By default this property will be blank meaning everything is enabled. Once you disable a protocol a value will get written for that protocol into the property. If you then re-enable the protocol this entry is not deleted rather one bit in the existing property is flipped. For example when I disable IMAP the following gets written into this property.

IMAP4§0§1§4§ISO-8859-1§0§1§0§0  (note because I'm an Aussie we use ISO character sets)

When you re-enable IMAP it just flips the first bit after the protocol IMAP4§0 from 0 to 1 eg

IMAP4§1§1§4§ISO-8859-1§0§1§0§0

So armed with this information to disable pop3 and imap on a mailbox with ADSI, (taking into account nothing has been set for HTTP because this will overwrite that property) you could use the following code (make sure you change the character set to whatever you use)

qstring = "LDAP://CN=USER,OU=wherver,DC=domain,DC=com"
set objUser = GetObject(qstring)
objUser.PutEx 2, "protocolSettings",ARRAY("POP3§0§1§4§ISO-8859-1§0§§§","IMAP4§0§1§4§ISO-8859-1§0§1§0§0")
objUser.setinfo
 
Flipping it back is a matter of using the same code with the reverse bits

qstring = "LDAP://CN=USER,OU=wherver,DC=domain,DC=com"
set objUser = GetObject(qstring)
objUser.PutEx 2, "protocolSettings",ARRAY("POP3§1§1§4§ISO-8859-1§0§§§","IMAP4§1§1§4§ISO-8859-1§0§1§0§0")
objUser.setinfo



Wednesday, July 28, 2004

Add creator to shared calender entry event sink

  One of the big pains i find when your using a shared calendar in a public folder is that you can't easily tell which user has created each of the calendar entries. I came up with the following sink for a small project I'm working on that will append the name of the creator to the location field of an appointment or meeting request when its created (this will mean it will appear in brackets when you look at the normal calendar view next to each appointment). You can grab the creator of a item from the "http://schemas.microsoft.com/mapi/proptag/0x3FF8001E" mapi property. 


Sub ExStoreEvents_OnSave(pEventInfo, bstrURLItem, lFlags)
on error resume next
Const EVT_NEW_ITEM = 1
Const EVT_IS_DELIVERED = 8

If (lFlags And EVT_IS_DELIVERED) Or (lFlags And EVT_NEW_ITEM) Then 
set apptobj = CreateObject("CDO.Appointment")
apptobj.datasource.open bstrURLItem,,3
creator = " Created by " & apptobj.fields("http://schemas.microsoft.com/mapi/proptag/0x3FF8001E").Value
apptobj.fields("urn:schemas:calendar:location") = apptobj.fields("urn:schemas:calendar:location") & creator
apptobj.fields.update
apptobj.datasource.save
end if
set apptobj = nothing

End Sub

  

Friday, July 23, 2004

BCC's with CDOEX

This one pops up now and again and can be a little bit of a pain to deal with in CDOEX. In the good old days of CDO 1.2 you could access the recipients collection of an email directly but with CDOEX you can't really do this, you only have a few properties which you can access. On a message the BCC field is an envelope field that you usually don't really care too much about, but when it comes to tasks and meeting requests the BCC field takes on a new perspective. In a task the BCC fields gets used for the StatusOnCompletionRecipients which controls who gets a task completion messages when a task is marked as complete and in a Meeting the BCC field is the resources field.

With meeting requests and appointments you can access the recipients collection via the IAttendees interface. So to add a BCC some code like this will work

Set appt = CreateObject("CDO.Appointment")
Set Atnd = Appt.Attendees.Add
Atnd.Address = "resource@yourdomain.com"
Atnd.Role = 2
Atnd.Type = "resource"


For a task you can't really do this but one way around this if you are creating a task (remembering that tasks aren't really supported in CDOEX anyway) is to first create a appointment add the number of people you want to the BCC and CC and then flip the messageclass and davcontent class values and save the item as a task. The only drawback with this method is you end up with a lot of redundant message properties and it only works on creation.

Set appt = CreateObject("CDO.Appointment")
Set Atnd = Appt.Attendees.Add
Atnd.Address = "completionnotify@domain.com"
Atnd.Role = 2
Atnd.Type = "resource"
Set Atnd1 = Appt.Attendees.Add
Atnd1.Address = "updatelist@domain.com"
Atnd1.Role = 1
Atnd1.Type = "Individual"
with appt
.Fields("DAV:contentclass").Value = "urn:content-classes:task"
.Fields("http://schemas.microsoft.com/exchange/outlookmessageclass").Value = "IPM.Task"
.Fields("urn:schemas:mailheader:subject").Value = "Test Task"
.Fields("urn:schemas:httpmail:textdescription").Value = "Blah"
.Fields("http://schemas.microsoft.com/mapi/proptag/0x82D9000B").Value = false
.Fields("http://schemas.microsoft.com/mapi/proptag/0x82BF0005").Value = 0
.Fields("http://schemas.microsoft.com/mapi/proptag/0x82C00003").Value = 0
.Fields("http://schemas.microsoft.com/mapi/proptag/0x82670003").Value = 0
.Fields("http://schemas.microsoft.com/mapi/proptag/0x82C00003").Value = 0
.Fields("http://schemas.microsoft.com/mapi/proptag/0x82C10003").Value = 0
.Fields.update
.datasource.saveto "file://./backofficestorage/yourdoain.com/mbx/mailbox/tasks/taskurl.eml"
end with

 
A better way to handle this might be to use WebDAV which is not inhibited in the same way in regards to BCC's.

Wednesday, July 21, 2004

Processing attachments in a embedded email message

I had a question from someone today about how to process the attachments on a embedded email (basically when you get an email that has another email attached to it which has attachments). The basic code to process a set of attachments on a message in Ex2k look like this

set msg = createobject("cdo.message")
msg.datasource.open "file://./backofficestorage/domain.com/MBX/user/Inbox/Mess.EML"
set objattachments = msg.attachments
for each objattachment in objattachments
     objattachment.savetofile "d:\temp\" & objattachment.filename
next


If you have an email with a embedded email as an attachment this embedded email will appear in the attachment well of the the other email as content type message/rfc822 but the filename will be blank and the above code would fail to execute at this step. To process these type of messages you need to open the embedded message from the bodypart and then process the attachments on this message. The other problem now is that the depth of embedded email could be greater then just one so this is when some sort of function you can call recursively is really needed within your code. Embedded email extraction is covered in the Exchange SDK here . Here's some code to extract multiple depth attachments in a multiple embedded message.

set msg = createobject("cdo.message")
msg.datasource.open "file://./backofficestorage/domain.com/MBX/user/Inbox/Mess.EML"
set objattachments = msg.attachments
for each objattachment in objattachments
if objAttachment.ContentMediaType = "message/rfc822" then
procattach(objattachment)
else
objattachment.savetofile "d:\temp\" & objattachment.filename
end if
next
set msg = nothing

function procattach(objattachment)
set msg1 = createobject("cdo.message")
msg1.datasource.OpenObject objattachment, "ibodypart"
set objattachments1 = msg1.attachments
for each objattachment1 in objattachments1
if objAttachment1.ContentMediaType = "message/rfc822" then
procattach(objattachment1)
else
objattachment1.savetofile "d:\temp\" & objattachment1.filename
end if
next
set msg1 = nothing
end function



Tuesday, July 20, 2004

Flip OOF status with OMA Script

The following script continues on from the other days post on scripting with OMA, I've been playing around with this a bit more and although its a bit funny in the way it responds I've come up with the following script which will logon to OMA navigate though all the menus to the OOF section and then change the OOF status. (kind of a lot like batch answer file scripting). I thought I would be cool to come up with a single button oof flipper application for a smart phone. 

ObjxmlHttp = CreateObject("Microsoft.XMLHTTP")
ObjxmlHttp.Open "get", "http://server/oma/(cvlbrraeffpq1xu5c013j055)/oma.aspx?", False, "domain\user", "password"
ObjxmlHttp.setRequestHeader "Accept-Language:", "en-us"
ObjxmlHttp.setRequestHeader "Content-type:", "application/x-www-UTF8-encoded"
ObjxmlHttp.setRequestHeader "Content-Length:", Len(xmlstr)
ObjxmlHttp.Send()
Wscript.echo ObjxmlHttp.responseText
slen = instr(ObjxmlHttp.responseText,"ufps") + 5
ufps = mid(ObjxmlHttp.responseText,slen,6)
fexe = navoma("__EVENTTARGET=c06&__EVENTARGUMENT=c0&__V_ViewStateKey=0",ufps)
slen = instr(fexe,"ufps") + 5
ufps = mid(fexe,slen,6)
if instr(fexe,"Change Password") then
fexe1 = navoma("__EVENTTARGET=c16&__EVENTARGUMENT=c1&__V_ViewStateKey=1",ufps)
else
fexe1 = navoma("__EVENTTARGET=c15&__EVENTARGUMENT=c1&__V_ViewStateKey=1",ufps)
end if
slen = instr(fexe1,"ufps") + 5
ufps = mid(fexe1,slen,6)
fexe2 = navoma("__EVENTTARGET=c20&__EVENTARGUMENT=c2&__V_ViewStateKey=2",ufps)
slen = instr(fexe2,"ufps") + 5
ufps = mid(fexe2,slen,6)
fexe3 = navoma("__EVENTTARGET=c22&__EVENTARGUMENT=c2&__V_ViewStateKey=3",ufps)
slen = instr(fexe3,"ufps") + 5
ufps = mid(fexe3,slen,6)
fexe4 = navoma("",ufps)
Set ObjxmlHttp = nothing

function navoma(szXml,ufps)
ostring = "http://server/oma/(cvlbrraeffpq1xu5c013j055)/oma.aspx?__ufps=" & ufps
ObjxmlHttp.Open "post",ostring , False
ObjxmlHttp.setRequestHeader "Accept-Language:", "en-us"
ObjxmlHttp.setRequestHeader "Content-type:", "application/x-www-form-urlencoded"
ObjxmlHttp.setRequestHeader "Referer:", ostring1
ObjxmlHttp.setRequestHeader "Content-Length:", Len(szXml)
ObjxmlHttp.Send szXml
Wscript.echo ObjxmlHttp.responseText
if instr(ObjxmlHttp.responseText,"Outlook(R) Mobile Access is returning you to
the main menu") then reset(ObjxmlHttp.responseText)
navoma = ObjxmlHttp.responseText
end function

function reset(response)
slen = instr(response,"ufps") + 5
ufps = mid(response,slen,6)
wscript.echo "start at " & ufps
slen = instr(response,"Out of Office:") + 15
szXml = "__EVENTTARGET=c01&__EVENTARGUMENT=c0&__V_ViewStateKey=1"
ostring = "http://server/oma/(cvlbrraeffpq1xu5c013j055)/oma.aspx?__ufps=" & ufps
ObjxmlHttp.Open "post",ostring , False
ObjxmlHttp.setRequestHeader "Accept-Language:", "en-us"
ObjxmlHttp.setRequestHeader "Content-type:", "application/x-www-form-urlencoded"
ObjxmlHttp.setRequestHeader "Referer:", ostring1
ObjxmlHttp.setRequestHeader "Content-Length:", Len(szXml)
ObjxmlHttp.Send szXml
slen = instr(ObjxmlHttp.responseText,"ufps") + 5
ufps = mid(ObjxmlHttp.responseText,slen,6)
Wscript.echo ObjxmlHttp.responseText
fexe = navoma("__EVENTTARGET=c06&__EVENTARGUMENT=c0&__V_ViewStateKey=0",ufps)
slen = instr(fexe,"ufps") + 5
ufps = mid(fexe,slen,6)
if instr(fexe,"Change Password") then
fexe1 = navoma("__EVENTTARGET=c16&__EVENTARGUMENT=c1&__V_ViewStateKey=1",ufps)
else
fexe1 = navoma("__EVENTTARGET=c15&__EVENTARGUMENT=c1&__V_ViewStateKey=1",ufps)
end if
slen = instr(fexe1,"ufps") + 5
ufps = mid(fexe1,slen,6)
end function


Wednesday, July 14, 2004

Scripting with OMA - Outlook Mobile Access

Continuing on from some of my other posts about using the Microsoft.XMLHTTP object to do some automation scripting with OWA I've started at looking at doing this in OMA as well. OMA is a lot less feature rich environment because it's designed for mobile devices but from a automation perspective this can be an advantage. There's very little information out there that covers how OMA work's from an indepth technical perspective (well that I could find anyway). But the basics of it is that its a ASP .NET application and from the reverse engineering I've looked at it passes some tokens and GUID looking parameters to make it work. As a starter script I created a simple script that uses the Microsoft.XMLHTTP object to list the contents of the inbox using OMA. Unlike OWA where you can just post a single command to the IIS server with OMA I found it required two requests. The first request logs onto OMA and gets the front page and more importantly a little token (the ufps thingy) that you must send with the post request to get it to work. I found you can specify your own GUID and this seems to work okay I guess as long as you are not using multiple clients with the same GUID. The only trick I found is that you must specify authentication in your open statement. I also haven't worked out how to target a mailbox other then the authentication user.


szXml = ""
Set ObjxmlHttp = CreateObject("Microsoft.XMLHTTP")
ObjxmlHttp.Open "get", "http://server/oma/(cvlbrraeffpq1xu5c013j055)/oma.aspx?", False, "domain\user", "password"
ObjxmlHttp.setRequestHeader "Accept-Language:", "en-us"
ObjxmlHttp.setRequestHeader "Content-type:", "application/x-www-UTF8-encoded"
ObjxmlHttp.setRequestHeader "Content-Length:", Len(xmlstr)
ObjxmlHttp.Send szXml
Wscript.echo ObjxmlHttp.responseText
slen = instr(ObjxmlHttp.responseText,"ufps") + 5
ufps = mid(ObjxmlHttp.responseText,slen,6)
szXml = "__EVENTTARGET=c00&__EVENTARGUMENT=c0&__V_ViewStateKey=0"
ostring = "http://server/oma/(cvlbrraeffpq1xu5c013j055)/oma.aspx?__ufps=" & ufps
ObjxmlHttp.Open "post",ostring , False, "domain\user", "password"
ObjxmlHttp.setRequestHeader "Accept-Language:", "en-us"
ObjxmlHttp.setRequestHeader "Content-type:", "application/x-www-form-urlencoded"
ObjxmlHttp.setRequestHeader "Referer:", "http://server/oma/(cvlbrraeffpq1xu5c013j055)/oma.aspx"
ObjxmlHttp.setRequestHeader "Content-Length:", Len(szXml)
ObjxmlHttp.Send szXml
Wscript.echo ObjxmlHttp.responseText

Wednesday, July 07, 2004

Sending a Mail via OWA from Script

Continuing on from some of my other posts I've done recently regarding reusing OWA commands such as this one I've come up with a script that uses the commands that OWA does to send a new email. Some of the advantages of this is that mail sent via this method ends up in the sent items of the sending mailbox. Its also acts as an alternative where you don't want to use CDO, ADO/Exoledb or WebDAV.


stmsgbody ="Hello Fred <BR<BR>"
stmsgbody = stmsgbody & "What to get some coffee Mate, Meet me downstairs in ten<BR><BR>"
stmsgbody = stmsgbody & "Cheers<BR>"
stmsgbody = stmsgbody & "Barney<BR>"
szXml = ""
szXml = szXml & "Cmd=send" & vbLf
szXml = szXml & "MsgTo=youruser@yourdomain.com" & vbLf
szXml = szXml & "MsgCc=" & vbLf
szXml = szXml & "MsgBcc=" & vbLf
szXml = szXml & "urn:schemas:httpmail:importance=1" & vbLf
szXml = szXml & "http://schemas.microsoft.com/exchange/sensitivity-long=" & vbLf
szXml = szXml & "urn:schemas:httpmail:subject=Coffee ???" & vbLf
szXml = szXml & "urn:schemas:httpmail:htmldescription=<!DOCTYPE HTML PUBLIC " _
& """-//W3C//DTD HTML 4.0 Transitional//EN""><HTML DIR=ltr><HEAD><META HTTP-EQUIV" _
& "=""Content-Type"" CONTENT=""text/html; charset=utf-8""></HEAD><BODY><DIV>" _
& "<FONT face='Arial' color=#000000 size=2>" & stmsgbody & "</font>" _
& "</DIV></BODY></HTML>" & vbLf
Set ObjxmlHttp = CreateObject("Microsoft.XMLHTTP")
ObjxmlHttp.Open "POST", "http://yourserver/exchange/yourmailbox/Drafts", False, "",""
ObjxmlHttp.setRequestHeader "Accept-Language:", "en-us"
ObjxmlHttp.setRequestHeader "Content-type:", "application/x-www-UTF8-encoded"
ObjxmlHttp.setRequestHeader "Content-Length:", Len(xmlstr)
ObjxmlHttp.Send szXml
Wscript.echo ObjxmlHttp.responseText

Friday, July 02, 2004

Tracking Email Delivery Time with WMI

One of the subjective problems in any email system is how long a message will take to reach its destination. Mail delivery times are never absolute and will always vary depending on a large number of variables out in the Big Wash (the Internet). Back in Exchange 5.5 one of the companies I used to work for used a software application that sent a mail via a poller and collector account and this is how they measured mail delivery times. In Exchange 2000 if you have message tracking logging enabled this information is actually keep on every message that is tracked in the Deliverytime property of the Exchange_MessageTrackingEntry WMI class. So if you have multiple servers at each point along the way you can look at the delivery time via WMI and you could actually work out how long this message is taking to be delivered over each hop.

So what i did today was write a script that looked at the two servers I've got in my production network and worked out firstly what was the delivery time of email from the point they hit my frount-end server and a 1024 event was logged in the message tracking logs to the point where they where delivered to the mailstore and a 1028 Event was logged on the mailbox server. Then you can work out the speed in bytes/second by divideing the size by the time taken. This didn't really present well as a text display so i think i'm going to need to put it in a database instead then maybe agregate the data to say 5 minute intervals and then graph it on a ASP page. You can also reverse the logic and look at outbound emails as well, this may be more interesting as you can then start graphing the delivery time to each different domain. Anyway here's the script (just reports on the last one hour of mailtraffic strcomputer in the frount-end strcomputer1 is the back-end)


strComputer = "frountend"
strComputer1 = "backend"
set shell = createobject("wscript.shell")
strValueName = "HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias"
minTimeOffset = shell.regread(strValueName)
toffset = datediff("h",DateAdd("n", minTimeOffset, now()),now())
dtListFrom = DateAdd("n", minTimeOffset, now())
dtListFrom = DateAdd("h",-1,dtListFrom)
strStartDateTime = year(dtListFrom)
if (Month(dtListFrom) < 10) then strStartDateTime = strStartDateTime & "0"
strStartDateTime = strStartDateTime & Month(dtListFrom)
if (Day(dtListFrom) < 10) then strStartDateTime = strStartDateTime & "0"
strStartDateTime = strStartDateTime & Day(dtListFrom)
if (Hour(dtListFrom) < 10) then strStartDateTime = strStartDateTime & "0"
strStartDateTime = strStartDateTime & Hour(dtListFrom)
if (Minute(dtListFrom) < 10) then strStartDateTime = strStartDateTime & "0"
strStartDateTime = strStartDateTime & Minute(dtListFrom)
if (Second(dtListFrom) < 10) then strStartDateTime = strStartDateTime & "0"
strStartDateTime = strStartDateTime & Second(dtListFrom) & ".000000+000"
Set objWMIService = Getobject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\MicrosoftExchangeV2")
Set objWMIService1 = Getobject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer1 & "\root\MicrosoftExchangeV2")
qstr = "Select * FROM Exchange_MessageTrackingEntry where entrytype = '1024' and OriginationTime > '" & strStartDateTime & "'"
Set colLoggedEvents = objWMIService.ExecQuery(qstr,,48)
For Each objEvent in colLoggedEvents
if instr(objEvent.Senderaddress,"@yourdomain.com.au") then

else
on error resume next
qstr1 = "Select * FROM Exchange_MessageTrackingEntry where entrytype = '1028' and TimeLogged > '" _
& strStartDateTime & "' and MessageID = '" & objEvent.MessageID & "'"
Set colLoggedEvents1 = objWMIService1.ExecQuery(qstr1,,48)
For Each objEvent1 in colLoggedEvents1
times = objEvent.Senderaddress & " " & objEvent.DeliveryTime & " " & objEvent1.DeliveryTime & " " _
& objEvent1.Size & " " & round(objEvent1.Size/objEvent1.DeliveryTime,0)
next
wscript.echo times
set colLoggedEvents1 = nothing
end if
next
wscript.echo "Done"

Thursday, July 01, 2004

Importing Message Tracking Logs into a Database without using WMI

A while ago I wrote a little Message Tracking Log application that I posted here on OutlookExchange. Somebody asked me today for a way to import a lot of tracking logs that they have archived in a directory where using WMI wasn't really going to be applicable. Fortunately this isn't that hard a thing to do, the message tracking logs are in essence a tab delimited text file with a few twists. The first twist is you really want to ignore the first 5 lines and the second is there is a double Line Feed at the end of each line. But because this is consistent it isn't hard to script around this.

So to do the hardwork of sorting out the tab delimited data in VBS you can use the Split command which will split the contents of each line into separate array elements where the delimiter separates the column. You still need to apply the same functions such as converting GMT time to local time and the time and data retrievals are a little different as they are stored in a little bit of a weird format.

The last hurdle was to front the code with something that would go though every file in a directory which can be done using the filesystem object.

The result was the following script that imports tracking log data into the database out of the article I mentioned.



set shell = createobject("wscript.shell")
strValueName = "HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias"
minTimeOffset = shell.regread(strValueName)
toffset = datediff("h",DateAdd("n", minTimeOffset, now()),now())
Set fso = CreateObject("Scripting.FileSystemObject")
Set Cnxn1 = CreateObject("ADODB.Connection")
strCnxn1 = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\Trackinglog.mdb;"
Cnxn1.Open strCnxn1
set f = fso.getfolder("c:\logdir")
Set fc = f.Files
For Each file1 in fc
wscript.echo file1.path
importtodb(file1.path)
next
wscript.echo "Done"

function importtodb(fname)
set wfile = fso.opentextfile(fname,1,true)
for i = 1 to 5
wfile.skipline
next
nline = wfile.readline
do until wfile.AtEndOfStream
if instr(nline," ") then
inplinearray = Split(nline, " ", -1, 1)
if inplinearray(8) = "1020" or inplinearray(8) = "1028" then
ClientIP = inplinearray(2)
if (isnull(ClientIP)) then ClientIP = "N/A"
Entrytype = inplinearray(8)
if (isnull(Entrytype)) then Entrytype = "N/A"
Subject = inplinearray(18)
if (isnull(Subject)) then Subject = "N/A"
RecipientAddress1 = inplinearray(7)
if (isnull(RecipientAddress1)) then RecipientAddress1 = "N/A"
RecipientCount = inplinearray(13)
if (isnull(RecipientCount)) then RecipientCount = "N/A"
SenderAddress = inplinearray(19)
if (isnull(SenderAddress)) then SenderAddress = "N/A"
size1 = inplinearray(12)
if (isnull(size1)) then size1 = "N/A"
datearray = split(inplinearray(0),"-",-1,1)
timearray = split(inplinearray(1),":",-1,1)
odate = dateserial(datearray(0),datearray(1),datearray(2))
otime = timeserial(timearray(0),timearray(1),0)
odate = dateadd("h",toffset,cdate(odate & " " & otime))
wtowrite = "('" & condate(odate) & "','" & formatdatetime(odate,4) & "','" & ClientIP & "','" & EntryType & "','" & RecipientCount & "','" & SenderAddress & "','" & RecipientAddress1 & "','" & left(replace(subject,"'"," "),254) & "','" & size1 & "')"
sqlstate1 = "INSERT INTO TrackingLogRaw ( [Date], [Time], [client-ip], [Event-ID], NoRecipients, [Sender-Address], [Recipient-Address], [Message-Subject], [total-bytes] ) values " & wtowrite
Cnxn1.Execute(sqlstate1)
end if
end if
nline = wfile.readline
loop
wfile.close
set wfile = nothing
end function


function condate(date2con)
dtcon = date2con
if month(dtcon) < 10 then
if day(dtcon) < 10 then
qdat = year(dtcon) & "0" & month(dtcon) & "0" & day(dtcon)
else
qdat = year(dtcon) & "0" & month(dtcon) & day(dtcon)
end if
else
if day(dtcon) < 10 then
qdat = year(dtcon) & month(dtcon) & "0" & day(dtcon)
else
qdat = year(dtcon) & month(dtcon) & day(dtcon)
end if
end if
condate = qdat
end function