pythonlinuxamazon-web-servicessendmail

Python Send Email with Base64 encoded image as attachment


I am trying to send emails from an AWS server using python and sendmail. (SES not available in my region). Using mail at the command line to send a basic email works fine. Now I am trying to do this from Python. I have the code below. It seems to run without error but no mail turns up in recipient email. Note that I am not sending attachments at this stage.

Maillog entries appear for the mail sent via python and via command line. Entries seem quite similar except "Message accepted for delivery" appears after the entries sent via command line.

What could be going wrong here? Where else might I look to find out what is going wrong? Is there an easier way to send email from Python / Linux?

import smtplib
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
from subprocess import Popen, PIPE

def send_mail(send_from, send_to, subject, text, files=None,
          server="127.0.0.1"):

msg = MIMEMultipart()
#msg['From'] = send_from
msg['To'] = send_to
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject

msg.attach(MIMEText(text))

# files should be a dictionary of filenames & base64 content 
for fname in files or {}:
    part = MIMEBase('image', 'jpeg')
    part.set_payload(files[fname])
    part.add_header('Content-Transfer-Encoding', 'base64')
    part['Content-Disposition'] = 'attachment; filename="%s"' % fname
    msg.attach(part)

print (msg.as_string())
p = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE)
p.communicate(msg.as_string())

Solution

  • So I am not sure where things went wrong. But I was on the right track. My final function is as follows below. This takes a base64 encoded list of images, are sent from my client application in JSON. Each image is in its own dictionary object with {filename: base64Data}.

    def send_mail(send_from, send_to, subject, text, files=None):
    msg = MIMEMultipart()
    msg["From"] = send_from
    msg["To"] = send_to
    msg["Subject"] = subject
    msg.attach(MIMEText(text))
    
    # files should be a dictionary of filenames & base64 content 
    for file in files or []:
        for key in file:
            part = MIMEBase('image', 'jpeg')
            part.set_payload(file[key])
            part.add_header('Content-Transfer-Encoding', 'base64')
            part['Content-Disposition'] = 'attachment; filename="%s"' % key
            msg.attach(part)
    
    # send the email by using send mail
    p = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE)
    p.communicate(msg.as_string())