Bounced messages: POP3 part

The sample demonstrates processing bounced messages.

In SMTP part of this sample we made bounce e-mails arrive to single e-mail account dedicated to bounced e-mails.

Each bounced e-mail contains (along with other info) e-mail address delivery has failed for. This failed address is what we want to know.

In this part, we retrieve bounced e-mails from dedicated account and then extract failed e-mail address from each bounced e-mail. Failed address is passed to RemoveEmailFromDatabase() subroutine which must remove failed address from database (in this sample, it does nothing).

Each mail server uses its own bounced message format. In this sample, typical bounced message is assumed to look like:

From: MAILER-DAEMON@iforum.com
To: MailBee@iForum.com
Subject: Undeliverable mail: A word from AfterLogic Support Team 

Failed to deliver to 'abc@you.com'
SMTP module(domain you.com) reports:
you.com: no DNS A-data returned

Modify GetInvalidEmailAddress() function to suit bounced e-mail format used by your mail server.

Note 1: Bounced e-mails arrived from another hosts will probably have different formats. In production code, you should support as many bounced e-mail formats as possible.

Note 2: You can eliminate necessity to parse bounced e-mail to get failed address by using wildcard mailbox for bounced e-mails account. However, this functionality greatly depends on particular mail server implementations and is not discussed here.

Note 3: In some cases, you may want to scan bounced e-mails for other information. E.g. do not remove e-mail address if bounced message arrived due temporary problem: mailbox is over quota, mail server is down, etc.

Visual Basic

Dim objPOP3, objMsgs, strEmail, I

' Create POP3 object
Set objPOP3 = CreateObject("MailBee.POP3")

' Enable logging POP3 session into a file
objPOP3.EnableLogging = True
objPOP3.LogFilePath = "C:\pop3_log.txt"

' Unlock POP3 object
objPOP3.LicenseKey = "put your license key here"

' Set POP3 server name
objPOP3.ServerName = "mail.server.com"

' Set user credentials
objPOP3.UserName = "username"
objPOP3.Password = "password"

' Connect to the server and log in the mailbox
If objPOP3.Connect Then

  ' Get headers + 100 body lines for all messages.
  ' 100 body lines is enough because failed address
  ' is somewhere in the beginning of the body
  Set objMsgs = objPOP3.RetrieveHeaders(100) 

  If Not objPOP3.IsError Then
    ' Loop through all messages in the mailbox
    For I = 1 To objMsgs.Count

      ' Get failed email address
      strEmail = GetInvalidEmailAddress(objMsgs(I))

      ' If strEmail is non-empty, failed email address
      ' was found
      If Len(strEmail) > 0 Then

        ' Remove failed email from database
        RemoveEmailFromDatabase strEmail

        ' Delete bounced email from server to avoid
        ' processing it next time
        objPOP3.DeleteMessage I
      End If
    Next
  Else
    ' Display error information
    MsgBox "Error #" & objPOP3.ErrCode & ", " & objPOP3.ErrDesc
  End If

  ' Close the connection
  objPOP3.Disconnect
Else
  ' Display error information
  MsgBox "Error #" & objPOP3.ErrCode
  MsgBox "Server response: " & objPOP3.ServerResponse
End If

' The functions checks whether the message
' is bounced and extracts failed address 
' from bounced message
Function GetInvalidEmailAddress(objMsg)
  Dim I1, I2

  GetInvalidEmailAddress = ""

  ' Check if this is a bounced message report
  If InStr(1, objMsg.FromAddr, "Mailer-Daemon", 1) < 1 Then Exit Function
  If InStr(1, objMsg.Subject, "Undeliverable mail", 1) <> 1 Then Exit Function

  ' Now we're sure this is a bounced message report

  I1 = InStr(1, objMsg.BodyText, "'", 0)
  I2 = InStr(I1 + 1, objMsg.BodyText, "'", 0)

  ' Message does not contain email address?
  If I1 < 1 Or I2 < 1 Then Exit Function

  ' Get failed address
  GetInvalidEmailAddress = Mid(objMsg.BodyText, I1 + 1, I2 - I1 - 1)

  ' E-mail address is often enclosed in "<>".
  ' Remove them if needed.
  If 
    Left(GetInvalidEmailAddress, 1) = "<" And Right(GetInvalidEmailAddress, 1) = ">" 
  Then
    GetInvalidEmailAddress = Mid(GetInvalidEmailAddress, 2, Len(GetInvalidEmailAddress) - 2)
  End If
End Function

' This function must remove (or disable) specified
' email address from mailing list
Sub RemoveEmailFromDatabase(strEmail)
  ' Do nothing for this demo
End Sub

ASP

<%
Dim objPOP3, objMsgs, strEmail, I

' Create POP3 object
Set objPOP3 = Server.CreateObject("MailBee.POP3")

' Enable logging POP3 session into a file
objPOP3.EnableLogging = True
objPOP3.LogFilePath = "C:\pop3_log.txt"

' Unlock POP3 object
objPOP3.LicenseKey = "put your license key here"

' Set POP3 server name
objPOP3.ServerName = "mail.server.com"

' Set user credentials
objPOP3.UserName = "username"
objPOP3.Password = "password"

' Connect to the server and log in the mailbox
If objPOP3.Connect Then

  ' Get headers + 100 body lines for all messages.
  ' 100 body lines is enough because failed address
  ' is somewhere in the beginning of the body
  Set objMsgs = objPOP3.RetrieveHeaders(100) 

  If Not objPOP3.IsError Then
    ' Loop through all messages in the mailbox
    For I = 1 To objMsgs.Count

      ' Get failed email address
      strEmail = GetInvalidEmailAddress(objMsgs(I))

      ' If strEmail is non-empty, failed email address
      ' was found
      If Len(strEmail) > 0 Then

        ' Remove failed email from database
        RemoveEmailFromDatabase strEmail

        ' Delete bounced email from server to avoid
        ' processing it next time
        objPOP3.DeleteMessage I
      End If
    Next
  Else
    ' Display error information
    Response.Write "Error #" & objPOP3.ErrCode & ", " & objPOP3.ErrDesc
  End If

  ' Close the connection
  objPOP3.Disconnect
Else
  ' Display error information
  Response.Write "Error #" & objPOP3.ErrCode & "<br>"
  Response.Write "Server response: " & objPOP3.ServerResponse
End If

' The functions checks whether the message
' is bounced and extracts failed address 
' from bounced message
Function GetInvalidEmailAddress(objMsg)
  Dim I1, I2

  GetInvalidEmailAddress = ""

  ' Check if this is a bounced message report
  If InStr(1, objMsg.FromAddr, "Mailer-Daemon", 1) < 1 Then Exit Function
  If InStr(1, objMsg.Subject, "Undeliverable mail", 1) <> 1 Then Exit Function

  ' Now we're sure this is a bounced message report

  I1 = InStr(1, objMsg.BodyText, "'", 0)
  I2 = InStr(I1 + 1, objMsg.BodyText, "'", 0)

  ' Message does not contain email address?
  If I1 < 1 Or I2 < 1 Then Exit Function

  ' Get failed address
  GetInvalidEmailAddress = Mid(objMsg.BodyText, I1 + 1, I2 - I1 - 1)

  ' E-mail address is often enclosed in "<>".
  ' Remove them if needed.
  If 
    Left(GetInvalidEmailAddress, 1) = "<" And Right(GetInvalidEmailAddress, 1) = ">" 
  Then
    GetInvalidEmailAddress = Mid(GetInvalidEmailAddress, 2, Len(GetInvalidEmailAddress) - 2)
  End If
End Function

' This function must remove (or disable) specified
' email address from mailing list
Sub RemoveEmailFromDatabase(strEmail)
  ' Do nothing for this demo
End Sub
%>

See Also:

Bounced messages: SMTP part