Search code examples
pythonemail-attachments

Im trying to attach an image to my email sender written python


Here is my code

import sys
import smtplib
import imghdr
from  email.message import EmailMessage
from tkfilebrowser import askopenfilename
from email.mime.base import MIMEBase
from email.encoders import encode_base64
from email import encoders

def send():
    msg = EmailMessage()
    msg['Subject'] = body
    msg['From'] = 'sender@gmail.com'
    msg['To'] = 'receiver@gmail.com'

it worked well until i added this below to attach an image

    with open('DSC_0020.jpg', 'rb') as f:
        mime =  MIMEBase('image', 'jpg', filename="DSC_0020.jpg")
        mime.add_header('Content-Dispotion', 'attachment', filename="DSC_0020.jpg")
        mime.add_header('X-Attachment-Id', '0')
        mime.add_header('Content-ID', '<0>')
        mime.set_payload(f.read())
        encoders.encode_base64(mime)
        mime.attach(mime)
                      
    msg.set_content('This is a plain text email')
    msg.add_alternative("""\
        <DOCTYPE html>
        <html>
            <body>
                <h1 style="color:gray;"> This is an HTML Email! </h1>
                <img src="body">
            </body>
        </html>
        """, subtype='html')

    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
        smtp.login('sender51@gmail.com', 'password')
        smtp.send_message(msg)

here is the error i get can someone tell me what im doing wrong

File "C:\Users\my name\AppData\Local\Programs\Python\Python38\lib\email\message.py", line 210, in attach raise TypeError("Attach is not valid on a message with a" TypeError: Attach is not valid on a message with a non-multipart payload


Solution

  • The main part of the email message should be of type MIMEMUltipart and then text content should be of type MIMEText as follows:

    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    # and, of course, other imports
    
    msg = MIMEMultipart('alternative') # to support alternatives
    msg['Subject'] = body
    msg['From'] = 'sender@gmail.com'
    msg['To'] = 'receiver@gmail.com'
    
    with open('DSC_0020.jpg', 'rb') as f:
        mime =  MIMEBase('image', 'jpg', filename="DSC_0020.jpg")
        mime.add_header('Content-Disposition', 'attachment', filename="DSC_0020.jpg") # corrected header
        mime.add_header('X-Attachment-Id', '0')
        mime.add_header('Content-ID', '<0>')
        mime.set_payload(f.read())
        encode_base64(mime) # improved statement (you can now get rid of following import: from email import encoders)
        msg.attach(mime) # corrected statement
    
    # Attach the plain text as first alternative
    msg.attach(MIMEText('This is a plain text email', 'plain'))
    # Attach html text as second alternative
    msg.attach(MIMEText("""\
        <DOCTYPE html>
        <html>
            <body>
                <h1 style="color:gray;"> This is an HTML Email! </h1>
                <img src="body">
            </body>
        </html>
        """, 'html'))
    

    You had some errors in your file processing block, which I tried to correct. There may have been others I did not catch.