Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending Mailgun Inline Images in HTML using Python Requests library

I am having trouble working out how I can send multiple inline messages using the Mailgun api, from a Python app using the requests library. Currently I have (using jinja2 for templates and flask as the webframework, hosted on Heroku):

def EmailFunction(UserEmail):
    Sender = '[email protected]'
    Subject = 'Hello World'
    Text = ''
    name = re.sub('@.*','',UserEmail)
    html = render_template('GenericEmail.html', name=name)
    images = []
    imageloc = os.path.join(dirname, 'static')
    images.append(open(os.path.join(imageloc,'img1.jpg')))
    images.append(open(os.path.join(imageloc,'img2.jpg')))
    send_mail(UserEmail,Sender,Subject,Text,html,images)
    return html

def send_mail(to_address, from_address, subject, plaintext, html, images):
    r = requests.\
        post("https://api.mailgun.net/v2/%s/messages" % app.config['MAILGUN_DOMAIN'],
            auth=("api", app.config['MAILGUN_KEY']),
             data={
                 "from": from_address,
                 "to": to_address,
                 "subject": subject,
                 "text": plaintext,
                 "html": html,
                 "inline": images
             }
         )
    return r

So the email sends fine, but no images are in the email at the end. When I click to download them they don't show. The images are referenced in the HTML as per the mailgun api (simplified of course!);

<img src="cid:img1.jpg"/>
<img src="cid:img2.jpg"/>
etc ...

Clearly I am doing something wrong, however I tried attaching these using the requests.files object, which didn't even send the email and gave no error so I assume that is not the right way at all.

Sadly the documentation on this is rather sparse.

Would it be better to have the HTML directly point the server side images? However this is not ideal as server side images in general will not be static (some will, some won't).

like image 885
Piers Lillystone Avatar asked Mar 08 '13 17:03

Piers Lillystone


2 Answers

As of 2020, actual documentation here: https://documentation.mailgun.com/en/latest/api-sending.html#examples

My example:

response = requests.post(
    'https://api.mailgun.net/v3/' + YOUR_MAILGUN_DOMAIN_NAME + '/messages',
    auth=('api', YOUR_MAILGUN_API_KEY),
    files=[
        ('inline[0]', ('test1.png', open('path/filename1.png', mode='rb').read())),
        ('inline[1]', ('test2.png', open('path/filename2.png', mode='rb').read()))
    ],
    data={
        'from': 'YOUR_NAME <' + 'mailgun@' + YOUR_MAILGUN_DOMAIN_NAME + '>',
        'to': [adresat],
        'bcc': [bcc_adresat],
        'subject': 'email subject',
        'text': 'email simple text',
        'html': '''<html><body>
            <img src="cid:test1.png">
            <img src="cid:test2.png">
            </body></html>'''
    },
    timeout=5  # sec
)
like image 70
Vladimir Pankov Avatar answered Oct 12 '22 06:10

Vladimir Pankov


Sending Inline Images is documented here.

In the HTML, you'll reference the image like this:

<html>Inline image here: <img src="cid:test.jpg"></html>

Then, define a Multidict, to post the files to the API:

files=MultiDict([("inline", open("files/test.jpg"))])

Disclosure, I work for Mailgun. :)

like image 38
Travis Swientek Avatar answered Oct 12 '22 06:10

Travis Swientek