mailgun/mailgun-go

Template Variables Are Individually Stringified Instead Of The Struct

kevineaton opened this issue · 1 comments

Hello,

I am trying to use the Mailgun-provided specific templates and attach data. However, the values are being all individually coerced into strings rather than the entire data set being stringified as a JSON object. This causes oddities, such as the inability to use {{#each}} on a data set (since the key is a string and the server is not seemingly trying to parse the JSON for each individual variable. For example, the following curl works just fine:

curl -s --user 'api:MY_KEY'
https://api.mailgun.net/v3/mail.domain.com/messages
-F from='Mailgun Sandbox <postmaster@mail.domain.com>'
-F to='Kevin Eaton <myemail>'
-F subject='Test'
-F template='school_warnings'
-F h:X-Mailgun-Variables='{"test": "test", "hasAlerts": true, "alerts": [{"subject": "test",
"body":"test", "level": "warning"}]}'

This Mailgun logs show this snippet for user variables:

	"user-variables": {
		"test": "test",
		"alerts": [
			{
				"body": "test",
				"subject": "test",
				"level": "warning"
			}
		],
		"hasAlerts": "true"
	},

However, due to the use of a map[string]string for message.variables, and the coercion in messages.go AddVariable, the value is coerced into a a string. Here is some sample code to send a message:

func SendMailExample() {
	myDomain := "snip"
	from := "snip"
	privateKey := "snip"
	to := "snip"

	// setup a new mailgun connection
	mg := mailgun.NewMailgun(myDomain, privateKey)
	message := mg.NewMessage(
		from,
		"This is a Sample Email",
		"")
	message.SetTemplate("school_alerts")
	message.AddRecipient(to)

	variables := map[string]interface{}{
		"hasAlerts": true,
		"alerts": []map[string]string{
			map[string]string{
				"level":   "Warning",
				"subject": "Test 1",
				"body":    "This is a test of an embedded warning",
			},
			map[string]string{
				"level":   "Alert",
				"subject": "Test 2",
				"body":    "This is a test of an embedded alert",
			},
		},
	}

	for k, v := range variables {
		message.AddVariable(k, v)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()
	mg.Send(ctx, message)
}

The Mailgun logs show the following for user variables:

	"user-variables": {
		"alerts": "[{\"body\":\"This is a test of an embedded warning\",\"level\":\"Warning\",\"subject\":\"Test 1\"},{\"body\":\"This is a test of an embedded alert\",\"level\":\"Alert\",\"subject\":\"Test 2\"}]",
		"hasAlerts": "true"
	},

which of course, Handlebars cannot parse as individual iterations using {{#each alerts}}. Also notice the the boolean for hasAlerts has been coerced into a string.

Am I missing something? Is there a way to send up embedded arrays? Could we change the message variables to be a map[string]interface{} and then JSON.marshal the entire variables struct into a string for the server?

I don't mind opening a PR to do it, but not quite sure the ramifications otherwise and if it would be something better approached some other way.

I think we can close this now. For anyone else having this issue See #201 for details on how to resolve.