Wrox Programmer Forums
| Search | Today's Posts | Mark Forums Read
ASP Pro Code Clinic As of Oct 5, 2005, this forum is now locked. No posts have been deleted. Please use "Classic ASP Professional" at: http://p2p.wrox.com/forum.asp?FORUM_ID=56 for discussions similar to the old ASP Pro Code Clinic or one of the other many remaining ASP and ASP.NET forums here.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the ASP Pro Code Clinic section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
  #1 (permalink)  
Old February 26th, 2004, 07:04 PM
Registered User
 
Join Date: Feb 2004
Location: , , .
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default CDO Email Errors not trapped by On Error

Hi,

I've got a problem where my apps email service is sporadic. Sometimes works like a charm, other times fails miserably.

What's supposed to happen is the following:
When an e-mail is successfully sent -- exit successfully and do nothing further.
When an error occurs on the email Send command
    1) Log the error # and description, body, subject, and distribution in a table
    2) Generate a message for the user explaining that the e-mail has NOT been sent, but everything else is OK
    3) Give them a link to redirect them so they continue as if no error had occurred.

Unfortunately, when the e-mail fails, nothing is recorded, nor is the user notified that an error occurred.

Any ideas?

(Note: Using Access 2000 on Win Server 2003)

Here is the code for all three procedures. Sorry if the indentation is messy...

Sub Sub_Process_Email_Error(str_Redirect)
    If str_Redirect <> "myFiles.asp" Then
        Response.Write "The E-mail was not sent due to an error. The QAS Developer has been notified and will resend the e-mail for you.<br>"
        Response.Write "All data was saved, and all other events have occurred.<br>"
        Response.Write "Please click <a href=" & str_Redirect & ">here</a> to continue."
        Response.End
    End If
End Sub

Sub Sub_Log_Email_Error(int_Err, str_Error, str_From,str_To, str_Cc, str_Subject, str_Body, str_Redirect)
    Dim rstError

    Set rstError = Server.CreateObject("ADODB.Recordset")
    Set rstError.ActiveConnection = obj_Connection
    rstError.Open "Select * From emailFailed",,3,3 'adOpenStatic, adLockOptimistic
    rstError.AddNew

    With rstError
        .Fields("str_From") = str_From
        .Fields("str_To").Value = str_To
        .Fields("str_Cc").Value = str_Cc
        .Fields("str_Subject").Value = str_Subject
        .Fields("str_Body").Value = str_Body
        .Fields("dtm_Date").Value = Now()
        .Fields("int_Err").Value = int_Err
        .Fields("str_ErrorDescription").Value = str_Error
        .Fields("isFailed").Value = True
    End With

    rstError.Update
    rstError.Close
    Set rstError = Nothing

    Call Sub_Process_Email_Error(str_Redirect)
End Sub

Sub Sub_Send_Email(str_From,str_To, str_Cc, str_Subject, str_Body, str_Redirect)
    If con_BlnEmailOn Then
        If con_BlnDebugEmail Then
            ' Developer is debugging email functions
            Response.Write "<p>"
            Response.Write "<b>FROM:</b>" & str_From & "<br>"
            Response.Write "<b>TO:</b>" & str_To & "<br>"
            Response.Write "<b>CC:</b>" & str_Cc & "<br>"
            Response.Write "<b>SUBJECT:</b>" & str_Subject & "<br>"
            Response.Write "<b>BODY:</b><br>"
            Response.Write "<pre>" & str_Body & "</pre>"
            Response.Write "</p>"
            Response.Write "<br><a href=" & str_Redirect & ">Continue</a>"
            Response.End
        Else
            ' Send Email
            If IsNull(str_From) OR IsNull(str_To) OR IsNull(str_Cc) OR IsNull(str_Subject) OR IsNull(str_Body) Then
                ' An error occurred, do nothing
            Else
                ' send the email message
                Dim obj_Email
                Dim iConf
                Dim Flds
                Dim int_Err
                Dim str_Error

                Const cdoSendUsingPort = 2

                Set obj_Email = CreateObject("CDO.Message")
                Set iConf = CreateObject("CDO.Configuration")
                Set Flds = iConf.Fields
                With Flds
                    .Item(cdoSendUsingMethod) = cdoSendUsingPort
                    .Item(cdoSMTPServer)= <remote server>
                    .Item(cdoSMTPServerPort) = 25
                    .Item(cdoSMTPconnectiontimeout) = 10
                    .Update
                End With

                Set obj_Email.Configuration = iConf

                obj_Email.From = str_From
                obj_Email.To = str_To
                obj_Email.Cc = str_Cc
                obj_Email.Subject = str_Subject
                obj_Email.HTMLBody = "<pre>" & str_Body & "</pre>"
                On Error Resume Next
                obj_Email.Send
                int_Err = Err.Number
                str_Error = Err.Description
                Err.Clear

                Set obj_Email = Nothing
                Set iConf = Nothing
                Set Flds = Nothing

                If int_Err <> 0 Then
                    Call Sub_Log_Email_Error(int_Err, str_Error, str_From,str_To, str_Cc, str_Subject, str_Body, str_Redirect)
                End If
            End If
        End If
    End If
End Sub

Thanks, Eric Bycer
  #2 (permalink)  
Old February 27th, 2004, 03:18 AM
Imar's Avatar
Wrox Author
Points: 70,322, Level: 100
Points: 70,322, Level: 100 Points: 70,322, Level: 100 Points: 70,322, Level: 100
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jun 2003
Location: Utrecht, Netherlands.
Posts: 17,089
Thanks: 80
Thanked 1,576 Times in 1,552 Posts
Default

Hi there,

Can you define "fails miserably"?

Is it possible that the CDO correctly drops the message with the server, but that it fails after that? E.G. I tell you to tell Jim something. As far as I am concerned, it is OK, because I told you to tell Jim. However, if you forget to tell Jim (or Jim just speaks Chinese), we have a problem...... ;)

Did you try to run the error handler code by throwing an error yourself? e.g. set int_Err to a non-zero value?

Imar


---------------------------------------
Imar Spaanjaars
Everyone is unique, except for me.
  #3 (permalink)  
Old February 27th, 2004, 08:33 AM
Registered User
 
Join Date: Feb 2004
Location: , , .
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi,

I suppose I should say it fails "gracefully" rather than miserably. When it fails, an e-mail is not sent, but the error handling procedure is not called, but no one knows it wasn't sent unless the receipient is later contacted. The usual error is "transport failed to connect to server" (IT has assured me that I have the correct remote server, and it does work sometimes...).

So, there's no log of the error, and no way for me to even attempt a resend.

To answer your second question, I have inserted an error, and at that point the error handler is called.

It seems as if something is going wrong with my "On Error" code, like unless I force it, it doesn't register Err.Number <> 0.
Should I not clear the error? Should I have the error handler code immediately following the .Send? I'm at a loss here, so any help you can provide will be most appreciated.

Thanks,

Eric Bycer
  #4 (permalink)  
Old February 27th, 2004, 09:02 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: Cardiff, , United Kingdom.
Posts: 231
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Your script could be timing out, however I would have thought that if this was the case then the client would be notified of the fact with an error page. If the script does time out then it will simply exit the routine it is on without generating any form of catchable error.

To test this write to a log file just before you call obj_Email.Send then write to the same log file just after the call. When the send does fail without being handled properly take a look at the log file and make sure that the second write exists, if it is not there then you know that the script has exited before it was completed, this may be because it timed out.

Regards
Owain Williams
  #5 (permalink)  
Old February 27th, 2004, 09:16 AM
Imar's Avatar
Wrox Author
Points: 70,322, Level: 100
Points: 70,322, Level: 100 Points: 70,322, Level: 100 Points: 70,322, Level: 100
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jun 2003
Location: Utrecht, Netherlands.
Posts: 17,089
Thanks: 80
Thanked 1,576 Times in 1,552 Posts
Default

AFAIK, the error handling code is fine. Whenever the Send method sets the Err.Number, the rest should work.
I tested this by setting the smtpserver to a non-existent server, and I got the usual "The transport failed to connect to the server" error message.

So, I still think that the error takes place after the Send method has been called. So, Send thinks everything is fine, and doesn't touch the Err.Number....



---------------------------------------
Imar Spaanjaars
Everyone is unique, except for me.
  #6 (permalink)  
Old February 27th, 2004, 01:21 PM
Registered User
 
Join Date: Feb 2004
Location: , , .
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

owain, Imar,

First off, thanks.

Second, I'm going to try owain's idea of writing to a log both before and after .Send. That should tell me which e-mails are failing.

And, while I suppose I could go through the log file to determine which e-mail sends failed and which did not, how can I best
a) get a list of failed e-mails populated into my emailFailed table, and
b) resend them?

If I have to do it the hard way, I can and will.

I'll try this over the weekend and see what happens.

Eric Bycer
  #7 (permalink)  
Old March 1st, 2004, 07:43 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: Cardiff, , United Kingdom.
Posts: 231
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Instead of having an emailFailed table you could, for example, call it EmailLogs. This table would contain columns for all the information you need to know about an email (To, From, Subject, Body, etc.) with an additional column Sent which would be set to True if the email was sent with no error.

Before you send an email you could add a new row with the details about the email, then if the send succeeds with no error you could change the Sent column for that row to True. If an error is generated or the script never completes then the Sent column will default to False. Here is a simplified version of the script you could use.
Code:
On Error Resume Next

rstEmailLog.AddNew
rstEmailLog("str_From") = str_From
rstEmailLog("str_To") = str_To
rstEmailLog("str_Cc") = str_Cc
rstEmailLog("str_Subject") = str_Subject
rstEmailLog("str_Body") = str_Body
rstEmailLog("dtmDate") = Now()
rstEmailLog.Update

obj_Email.From = str_From
obj_Email.To = str_To
obj_Email.Cc = str_Cc
obj_Email.Subject = str_Subject
obj_Email.HTMLBody = "<pre>" & str_Body & "</pre>"

obj_Email.Send
int_Err = Err.Number
str_Error = Err.Description
Err.Clear

If int_Err = 0 Then
    rstEmailLog("Sent") = True
    rstEmailLog.Update
Else
    rstEmailLog("Sent") = False
    rstEmailLog("int_Err") = int_Err
    rstEmailLog("str_ErrorDescription") = str_Error
    rstEmailLog.Update
End If
You could then have another script that is scheduled to run as often as is required. This script would scan through the EmailLogs table looking for all emails where the Sent column is False. Again, the column would only be set to True if no error is generated and the script completes.
Code:
On Error Resume Next

rstEmailLog.Open "SELECT * FROM EmailLog WHERE Sent = False", , 3, 3
Do Until rstEmailLog.EOF
    obj_Email.From = rstEmailLog("str_From")
    obj_Email.To = rstEmailLog("str_To")
    obj_Email.Cc = rstEmailLog("str_Cc")
    obj_Email.Subject = rstEmailLog("str_Subject")
    obj_Email.HTMLBody = "<pre>" & rstEmailLog("str_Body") & "</pre>"
    obj_Email.Send
    int_Err = Err.Number
    str_Error = Err.Description
    Err.Clear
    If int_Err = 0 Then
        rstEmailLog("Sent") = True
        rstEmailLog("int_Err") = 0
        rstEmailLog("str_ErrorDescription") = ""
        rstEmailLog.Update
    Else
        rstEmailLog("Sent") = False
        rstEmailLog("int_Err") = int_Err
        rstEmailLog("str_ErrorDescription") = str_Error
        rstEmailLog.Update
    End If
    rstEmailLog.MoveNext
Loop
Because of the possibility of the script timing out the results of the query might need to be returned to the client the then each email may need to be re-sent manually. This could be automated by JavaScript, however that is an entirely new thread :).

You may also want to include a counter column that would be incremented every time you try and send the email so you can see if certain emails are never being sent, these could be larger emails, or emails with large attachments that are not being sent before the script times out.

Regards
Owain Williams


Similar Threads
Thread Thread Starter Forum Replies Last Post
CDO Email error Treefarn Classic ASP Professional 10 February 20th, 2007 02:39 PM
CDO external email error in ASP Robert02 Classic ASP Professional 0 July 5th, 2006 04:28 PM
error sending email with attachment using CDO archanahs Classic ASP Professional 1 May 25th, 2006 08:16 AM
CHR(13) errors in CDO.CreateMHTMLBody() janaka44 Classic ASP Professional 0 April 5th, 2006 11:08 PM
Email Problem - CDO SYS Error itHighway Classic ASP Basics 1 August 25th, 2005 05:14 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.