Mailgun and OpenInsight: Checking Bounced Messages

This blog post demonstrates an easy way to utilize Mailgun for checking bounced email messages sent through the Mailgun managed email service. With a few bits of information from your free Mailgun account you can begin checking if your messages were delivered. This blog post continues where Mailgun and OpenInsight: Getting Started ended so if you're not familiar with Mailgun or why it's incredibly useful I encourage you to review the post before continuing on.

Required Information

Before beginning this process you'll need some test data and account information. We'll walk through it step by step.

  1. Generate a bounced message by sending email through mailgun to a non-existent email account. In my example I'll use the address

    Tip: You can use the example program from the getting started blog post or use any email client with your mailgun account information to generate the bounced message.
  2. Use the mailserver logs screen in the Mailgun control panel to verify the email bounced. The image below shows recent mail log entries for and the bounced test message for

    If you don't see the log entry for your bounced message be sure the correct domain was selected.
  3. Go to the main Mailgun control panel screen and note the API Key and domain name. You'll need the information later. The API key is secret and should be protected just as you would a password. The image below shows where the API key and domain name are located.

We now have all the information needed to check for bounced messages from within OpenInsight code.

Example Code

Create a new stored procedure based on the following program. You'll need to change the following variables and replace each with your information from the previous section:

  • CheckAddressBounced
  • APIKey
  • APIDomain

See the variable comments for more information.

Function mailgun_check_bounce(params)
* Description:  Simple example problem to query the MailGun email server to check for if the
*				specified email address bounced and get the reason why.
*				Program demonstrates the use of WinHTTP COM Object and JSON values.
*				Example use only. Requires configuration of static variables for example.
*				Set CheckAddressBounced, APIKey, APIDomain before use.
* Parameters:
*   none
* Returns:
*	none
* History (Date, Initials, Notes)
* 08/20/14    JAB    Jared Bratu, Congruity Service

Declare Function RTI_JSON

Equ MAILGUN_ADDRESS_NOT_FOUND$ To "Address not found in bounces table"
Equ TRUE$ To 1
Equ FALSE$ To 0

*Address to check. Check if email sent to this address bounced.
CheckAddressBounced = ''

*The mailgun private API Key available on the control panel
APIKey 		= "key-replacewithyourapikey" ;* Replace with your key
APIUserName = "api" ;*This should always be 'api' as per mailgun docs

*The mailgun account domain the CheckAddresBounce address was sent through 
APIDomain 	= "" ;* Replace with your domain

*Construct the API URL call according to the MailGun docs
APIUrl 		= "" : APIDomain : "/bounces/" : CheckAddressBounced

*Break to debug on error
DebugOnError = TRUE$

LOG = "Checking if " : CheckAddressBounced : " bounced."
Gosub mcbSetLog

*Construct an HTTP request and set the Open parameters
oleObj = OleCreateInstance('WinHttp.WinHttpRequest.5.1')
oleResult = OleCallMethod(oleObj, "Open", 'GET', APIUrl, 0)
mcbStep = "Setting WinHTTP Open Parms"	
mcbStatus = OleStatus() ; Gosub mcbCheckStatus

*Optional - Setup timeout methods for resolving DNS and server response
mcbStatus = OleCallMethod(oleObj, "SetTimeouts", 30000,15000,15000,15000) ;* All times in ms
mcbStep = "Setting timeout values"	
mcbStatus = OleStatus() ; Gosub mcbCheckStatus

*Specify the username and password to authenticate with the API as	
oleResult = OleCallMethod(oleObj, "SetCredentials", APIUserName, APIKey, 0)
status = OleStatus()
mcbStep = "Setting user and pass"	
mcbStatus = OleStatus() ; Gosub mcbCheckStatus

*Execute the API request call	
*Blocks until Timeout reached or response received
oleResult = OleCallMethod(oleObj, 'SEND')
mcbStep = "Executing request"	
mcbStatus = OleStatus() ; Gosub mcbCheckStatus

*Get the response value or error value
ResponseRAW = OleGetProperty(oleObj, 'ResponseText')
mcbStep = "Reading ResponseText"		
mcbStatus = OleStatus() ; Gosub mcbCheckStatus

*If authentication fails we don't get a JSON object
	LOG = "Unrecoverable authentication error"
	Gosub mcbSetLog
End Else

	bounce = ''
	*Branch will set bounce to true of bounced or false if not bounced
	Gosub mcbProcessResponse

If Unassigned(bounce) Then
	*Fatal error, couldn't determine bounce status
	*Check mcbLog variable for details
End Else
	If bounce = TRUE$ Then
		*Message bounced
		*see mcbLog variable for details
	End Else
		*Message did not bounce



* Branch handles a successful API call.
* Requires:
* ResponseRAW
* Returns:
* Bounce

*Turn the raw response into a JSON object for manipulation	
RetObj = RTI_JSON(ResponseRAW, 'Parse')
ResponseMessage = RTI_JSON(RetObj, "GetValue", "message")

	bounce = FALSE$
	mcbLog = "Address " : CheckAddressBounced : " did not bounce"
	Gosub mcbSetLog
End Else
	bounce = TRUE$
	RetObjValues = RTI_JSON(RetObj, "GetObject", "bounce")
	bounce_code = RTI_JSON(RetObjValues, 'GetValue', 'code')
	bounce_error = RTI_JSON(RetObjValues, 'GetValue', 'error')
	bounce_address = RTI_JSON(RetObjValues, 'GetValue', 'address')
	mcbLog = "Address " : bounce_address : " bounced with error " : bounce_code : ". Error: " : bounce_error
	Gosub mcbSetLog


* Branch to log errors into LOG
*mcb = MailGun Check Bounce	

	If mcbStatus then
		Log = mcbStep : ' code: ': mcbStatus 
		* If we want to break on error then
		* reference the error variables for easy access
		If DebugOnError EQ TRUE$ Then
			LOG_ALL = mcbLog
			LOG_LAST = Log
		Gosub mcbSetLog
Return ;*etiwagapomd

* Simple concatenation or logging function.
	If Unassigned(mcbLog) Then 
		mcbLog = LOG
	End Else
		mcbLog<-1> = LOG
Return ;*etiwagapomd

If the program variables are assigned correctly and the test succeeds it should break to the debugger and in variable mcbLog<1> contain:

Address bounced with error 550. Error: 550 Requested action not taken: mailbox unavailable

This demonstrates that OpenInsight was able to query the Mailgun service using the web API to check if email sent to a particular address was delivered or not. More information about the API is available at the Mailgun Bounce documentation page.

The next blog entry in this series will document parts of the test program since the code will be the basis for all remaining postings in the rest of this series. Like any eager developer, I want to invest a minimal amount of effort to see a result before I commit to diving in to the details. Those details are coming.

Share this post

Leave a comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
5 + 3 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.

About Us

Congruity Service is a technology solutions company bringing the best technology solutions to OpenInsight projects, Drupal sites, servers, networks, and your technology needs.