According to HTML-Email with inline attachments and non-inline attachments, the MIME way is to build an inner mime/related message containing both the HTML text and the inline image(s), and an outer one containing the mime/related message and the other attachment(s).
Your code could become
...
message_body = """<html>
<body><p>Please keep in touch and reach out to us for any help needed.</p>
<image src="cid:image"/></body></html>"""
msg = MIMEMultipart("mixed")
message_body = """<html>
<body><p>Please keep in touch and reach out to us for any help needed.</p>
<image src="cid:image"/></body></html>"""
msg = MIMEMultipart("mixed")
msg['From'] = username
msg['To'] = ','.join(to)
msg['Subject'] = subject
body = MIMEText(message_body, \
'html', 'utf-8')
inner = MIMEMultipart("related")
inner.attach(body)
msg.attach(inner)
...
image = MIMEImage(img_data, name=os.path.basename(x))
image.add_header('Content-Id', 'image')
inner.attach(image)
image_1 = MIMEImage(img_data_1, name=os.path.basename(y))
msg.attach(image_1)
...
After @triplee's comment, I gave a try to the EmailMessage
API. It comes with far more black magic, so things are much simpler if less explicit:
from email.message import EmailMessage
from imghdr import what
...
message_body = """<html>
<body><p>Please keep in touch and reach out to us for any help needed.</p>
<image src="cid:image"/></body></html>"""
msg = EmailMessage()
message_body = """<html>
<body><p>Please keep in touch and reach out to us for any help needed.</p>
<image src="cid:image"/></body></html>"""
msg = MIMEMultipart("mixed")
msg['From'] = username
msg['To'] = ','.join(to)
msg['Subject'] = subject
msg.set_content(message_body, subtype='html')
...
msg.add_related(img_data, 'image', what(x), cid='image')
msg.add_attachment(img_data_1, 'image', what(y),
filename=os.path.basename(y))
...