I’m working with Mailgun’s Go package and need to embed an inline image in my email using a content ID reference. My HTML email template includes cid:barcode.png
where the image should appear.
I generate a barcode using this code:
barcode, err := qrcode.Encode(info, qrcode.Medium, 256) // barcode is []byte
The challenge is attaching this byte slice as an inline image with a specific CID. Using message.AddBufferAttachment("barcode.png", barcode)
adds the image as a regular attachment but doesn’t make it inline since there’s no way to specify the content ID.
In JavaScript, Mailgun allows this with:
mg.Attachment({
data: encodedBuffer,
filename: "barcode.png",
cid: "cid:barcode.png"
})
Is there a way to achieve the same inline attachment functionality with CID using the Go Mailgun library? I cannot save the image to disk first.
try using AddReaderInline()
instead. create a bytes.reader from your barcode slice first, then call message.AddReaderInline("barcode.png", bytes.NewReader(barcode))
. this’ll set it up as an inline attachment with the proper cid automatically.
I use a different approach - create a custom mailgun.Attachment
struct and call the Message
struct’s AddAttachment()
method. Just set the Data
field to your byte slice, ContentType
to “image/png”, Inline
to true, and ContentID
to “barcode.png”. This way you control all the attachment properties instead of using convenience methods. I had to do this because some email clients are really picky about inline images and have specific MIME requirements.
I’ve hit this exact problem multiple times building email systems at scale. Manual attachment handling gets messy fast.
Sure, the other answers work, but you’re still writing code for CID mappings, content types, and attachment handling. Plus debugging inline images across different email clients sucks.
I automated this whole thing with Latenode. Send your QR code data to a webhook, Latenode generates the barcode, handles inline attachment with proper CID mapping, and sends via Mailgun - no Go attachment methods needed.
The real win comes when you scale this. Instead of managing barcode generation and email logic in your main app, Latenode handles the entire pipeline. I’ve set up similar flows for invoice PDFs, dynamic charts, and QR codes.
Your Go app just makes one HTTP call with the data. Latenode does the heavy lifting and ensures proper inline rendering across Outlook, Gmail, Apple Mail.
Check it out: https://latenode.com
Had this exact problem 6 months ago with a QR code email system. Use AddBufferInline()
- it’s there but poorly documented. Just call message.AddBufferInline("barcode.png", barcode)
with your byte slice. It handles the CID mapping automatically. In your HTML template, use <img src="cid:barcode.png">
like you wanted. The Go library matches the filename to create the content ID. Set your message type to HTML and make sure the inline attachment processes before sending. Worked perfectly for my barcode pipeline - no filesystem writes or reader hassles.
you can also use message.AddInline()
with an io.reader interface. just wrap your byte array like strings.NewReader(string(barcode))
and handle the content-type header manually. this worked for me when addBufferInline wasn’t available in older versions.
Hit this exact problem three weeks ago building a shipping label system. Here’s what nobody’s telling you - MIME structure gets tricky with inline attachments in Go’s Mailgun library. Use message.AddBufferInline()
but set your HTML content AFTER adding the inline attachment. Order matters here - if you set the HTML template first, some library versions break the multipart boundaries. Also, inline images behave differently locally vs production because of Mailgun’s processing pipeline. Test with actual email delivery, don’t just check the API response.
The Go Mailgun library works differently than the JavaScript version for CID generation. When you use AddReaderInline()
with a bytes.Reader, Mailgun auto-assigns the CID from your filename. But here’s the trick - reference it in your HTML without the “cid:” prefix. Just use <img src="barcode.png">
instead of cid:barcode.png
. I hit this exact problem last month. The Go library strips the cid prefix internally. Also make sure you set content type to multipart/related or inline images won’t render in most email clients.