mailgun/mailgun-go

API base URL cannot be changed

henhouse opened this issue · 10 comments

The base API URL seems to be pointed to the US API currently, with no indication that you need to change it to point to EU if your domain is set there. Instead, you're met with a 404 error telling you your domain is not found.

When attempting to call SetAPIBase() to set the URL to the EU API, you are unable to include the https:// because you will get this error: invalid character 'M' looking for beginning of value. If you leave out the scheme thinking it will be set by default, you get a POST failure due to the missing scheme: unsupported protocol scheme.

Edit: Turns out the trailing /v3 is essential for this to work. This is very confusing, and there doesn't seem to be any direct documentation telling you to switch region, or how to properly. Perhaps the mailgun.NewMailgun() should take a third, regional type to specify which API endpoint to be hitting?

@henhouse thanks for the feedback! We should at least document this to ease the pain of using this library in EU. I'm hesitant to change the signature of mailgun.NewMailgun() as it would require a major version bump. Perhaps we could add a mg.SetRegion() method. This would make it an additive change and not require a version bump. Thoughts?

yes i also find this question, unexpected error: invalid character 'M' looking for beginning of value but iam not eu ,i am from china, i don't known why

@thrawn01 Ah, that makes sense. For compatibility's sake, this change looks good. The added documentation is exactly what I was looking for when using this earlier, so I suspect most confused people will see this now and be led in the right direction now. Nice!

@CNbluer
Use mg.SetAPIBase("https://api.eu.mailgun.net/v3") if your domain is set to Mailgun's EU API server.
Or if US, use: mg.SetAPIBase("https://api.mailgun.net/v3")

I've had some thoughts on this as we switched to EU servers (due to GDPR concerns).

If there are only these two possible values for the API base why not just hardcode them in? The only case I see where changing it to something completely different is in testing and that can be done by private fields and/or build tags.

My preferred way of doing this would be in the initialization, something like

mg := mailgun.NewMailgun(yourDomain, privateAPIKey, mailgun.EURegion)

or

mg := mailgun.NewMailgunEURegion(yourDomain, privateAPIKey)

@mbanzon I agree, when we are ready to bump the release version to v4 we should add the region as an argument to NewMailgun().

@CNbluer I will add a check for URL's passed to SetAPIBase(). If the URL doesn't end with a /v* then It will return an appropriate error instead of unexpected error: invalid character 'M'

@thrawn01 Hey Derrick, despite targeting 3.6.1-rc.3, I am still getting invalid character 'M' looking for beginning of value

Not surprisingly, I get the same if I pass the url directly: mg.SetAPIBase("https://api.eu.mailgun.net/v3")

Am I missing a step other than mg.SetAPIBase and using 3.6.1 rc3?

@DanielHouston could you post a code sample? Perhaps the domain name includes a unicode character that I'm not testing for? or Punycode? Here is my test code for EU which works for me.

func main() {
	mailgun.Debug = true
	mg := mailgun.NewMailgun("<my-eu-domain>", "<api-key>")

	mg.SetAPIBase(mailgun.APIBaseEU)

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
	defer cancel()

	it := mg.ListDomains(nil)
	var page []mailgun.Domain
	for it.Next(ctx, &page) {
		for k, v := range page {
			fmt.Printf("\tDomain: [%d] - %+v\n", k, v)
		}
	}
}

Sorry for the radio silence. This turned out to be a user error, caused by including the scheme in "", once I removed it, my code (similar to your test code) worked.

It's likely you are getting a 401 error when sending a message via mailgun.js if your account was created in the EU. You can resolve this problem by configuring the following options.
this configuration is only for eu region
for node js :

const Mailgun = require('mailgun.js')
const formData = require('form-data')
const mailgun = new Mailgun(formData)

const mg = mailgun.client({
  username: <MAILGUN_USERNAME>,
  key: <MAILGUN_KEY>,
  url:"https://api.eu.mailgun.net/"
})

const sendMail = async () => {
const response = await mg.messages.create(process.env.MAILGUN_DOMAIN,
    {
      from: 'vault <postmaster@Domain>',
      to: [mailReceiver],
      subject: 'Coming soon',
      text: "content"
    })
return response;
}