Python Send Html, Image And Attachment Email Example

In the last article Python SMTP Send Email Example we had learned how the email transfer from the internet to the receiver’s email address, we have also learned the basic source code to send email to the SMTP server in the Python program. In this article, we will tell you how to send more complex email content such as Html format content, image, and attachment through the SMTP server.

1. Send HTML Content In Email.

  1. What if we want to send HTML messages instead of plain text in email?
  2. The method is simple. When you construct the MIMEText object, pass in the HTML string, and change the second parameter from ‘plain‘ to ‘HTML‘, other codes are the same.
  3. When you send the email again, you can see Html content in the email body.
    from email.MIMEText import MIMEText
    msg = MIMEText('<html><body><h1>Hello World</h1>' +
    '<p>this is hello world from <a href="http://www.python.org">Python</a>...</p>' +
    '</body></html>', 'html', 'utf-8')

2. Send Email With Attachments.

  1. Mail with attachments can be regarded as mail with several parts: text and attachments.
  2. So, we can construct a MIMEMultipart object to represent the mail itself, then add a MIMEText object that contains email content to the mail body. And then add a MIMEBase object to the mail body to represent the attachment.
  3. Then, follow the normal send process to send the message ( MIMEMultipart object ) to an SMTP server, then the email with attachments will be received.
    from email.MIMEMultipart import MIMEMultipart
    from email.MIMEText import MIMEText
    
    # get user input
    # input sender email address and password:
    from_addr = input('From: ')
    password = input('Password: ')
    # input receiver email address.
    to_addr = input('To: ')
    # input smtp server ip address:
    smtp_server = input('SMTP server: ')
    
    # email object that has multiple part:
    msg = MIMEMultipart()
    msg['From'] = from_addr
    msg['To'] = to_addr
    msg['Subject'] = Header('hello world from smtp server', 'utf-8').encode()
    
    # attache a MIMEText object to save email content
    msg_content = MIMEText('send with attachment...', 'plain', 'utf-8')
    msg.attach(msg_content)
    
    # to add an attachment is just add a MIMEBase object to read a picture locally.
    with open('/Users/jerry/img1.png', 'rb') as f:
        # set attachment mime and file name, the image type is png
        mime = MIMEBase('image', 'png', filename='img1.png')
        # add required header data:
        mime.add_header('Content-Disposition', 'attachment', filename='img1.png')
        mime.add_header('X-Attachment-Id', '0')
        mime.add_header('Content-ID', '<0>')
        # read attachment file content into the MIMEBase object
        mime.set_payload(f.read())
        # encode with base64
        encoders.encode_base64(mime)
        # add MIMEBase object to MIMEMultipart object
        msg.attach(mime)
    
    server = smtplib.SMTP(smtp_server, 25)
    server.set_debuglevel(1)
    server.login(from_addr, password)
    server.sendmail(from_addr, [to_addr], msg.as_string())
    server.quit()

3. Send Email With Image.

  1. What if you want to embed an image in the body of the mail? Is it okay to link the image address directly in HTML mail?
  2. The answer is that most email service providers automatically block pictures with external links because they don’t know whether these links point to malicious websites or not.
  3. To embed the image into the body of the mail, we just need to add the image as an attachment in the way of sending attachments.
  4. Then, in HTML, we can embed the attachment as an image by referring an image to src= “cid:0”.
  5. If you have multiple pictures, number them in turn and then refer each image to a different cid: x(image number).
    from email.MIMEText import MIMEText
    
    msg.attach(MIMEText('<html><body><h1>Hello</h1>' +
    '<p><img src="cid:0"></p>' +
    '</body></html>', 'html', 'utf-8'))

4. Support Both HTML And Plain Text Formats.

  1. If we send HTML mail, the recipient can browse the content of the mail normally through the browser or software such as Outlook.
  2. But what if the device used by the recipient is too old to view HTML mail?
  3. The solution is to attach plain text while sending HTML. If the recipient can’t view the mail in HTML format, it can automatically degrade to view the plain text mail.
  4. Using MIMEMultipart, you can combine HTML and Plain Text content in one email. Note that subtype should be an alternative.
    from email.MIMEMultipart import MIMEMultipart
    from email.MIMEText import MIMEText
    
    # Pass 'alternative' to the MIMEMultipart constructor.
    msg = MIMEMultipart('alternative')
    msg['From'] = input('From: ')
    msg['To'] = input('To: ')
    msg['Subject'] = input('Subject: ')
    
    msg.attach(MIMEText('hello this is a plain text version.', 'plain', 'utf-8'))
    msg.attach(MIMEText('<html><body><h1>Hello this is html version</h1></body></html>', 'html', 'utf-8'))

5. Encrypted SMTP.

  1. When connecting to an SMTP server using standard port 25, it uses plaintext transmission, and the whole process of sending mail may eavesdrop.
  2. To send email safer, you can encrypt SMTP sessions, which is essential to create an SSL secure connection before sending mail using the SMTP protocol.
    # define smtp server domain and port number.
    smtp_server = 'smtp.yahoo.com'
    smtp_port = 989
    # create smtp server object.
    server = smtplib.SMTP(smtp_server, smtp_port)
    # use ssl protocol to secure the smtp session connection, all the data transferred by the session will be secured. 
    server.starttls()
    # send the email as normal.
    server.set_debuglevel(1)

6. Send Both Html, Image & Alternative Text Example.

  1. This example will use Python to send an email with HTML content, if the email client is too old to support HTML content, it also sends an alternate text content with it.
  2. The below source code embed an image in the email Html content also.
    # Import smtplib library to send email in python.
    import smtplib
    # Import MIMEText, MIMEImage and MIMEMultipart module.
    from email.MIMEImage import MIMEImage
    from email.MIMEMultipart import MIMEMultipart
    from email.MIMEText import MIMEText
    
    # Define the source and target email address.
    strFrom = '[email protected]'
    strTo = '[email protected]'
    
    # Create an instance of MIMEMultipart object, pass 'related' as the constructor parameter.
    msgRoot = MIMEMultipart('related')
    # Set the email subject.
    msgRoot['Subject'] = 'This email contain both Html, text and one image.'
    # Set the email from email address.
    msgRoot['From'] = strFrom
    # Set the email to email address.
    msgRoot['To'] = strTo
    
    # Set the multipart email preamble attribute value. Please refer https://docs.python.org/3/library/email.message.html to learn more.
    msgRoot.preamble = '====================================================='
    
    # Create a 'alternative' MIMEMultipart object. We will use this object to save plain text format content.
    msgAlternative = MIMEMultipart('alternative')
    # Attach the bove object to the root email message.
    msgRoot.attach(msgAlternative)
    
    # Create a MIMEText object, this object contains the plain text content.
    msgText = MIMEText('This object contains the plain text content of this email.')
    # Attach the MIMEText object to the msgAlternative object.
    msgAlternative.attach(msgText)
    
    # Create a MIMEText object to contains the email Html content. There is also an image in the Html content. The image cid is image1.
    msgText = MIMEText('<b>This is the <i>HTML</i> content of this email</b> it contains an image.<br><img src="cid:image1"><br>', 'html')
    # Attach the above html content MIMEText object to the msgAlternative object.
    msgAlternative.attach(msgText)
    
    # Open a file object to read the image file, the image file is located in the file path it provide.
    fp = open('/usr/var/test.jpg', 'rb')
    # Create a MIMEImage object with the above file object.
    msgImage = MIMEImage(fp.read())
    # Do not forget close the file object after using it.
    fp.close()
    
    # Add 'Content-ID' header value to the above MIMEImage object to make it refer to the image source (src="cid:image1") in the Html content.
    msgImage.add_header('Content-ID', '<image1>')
    # Attach the MIMEImage object to the email body.
    msgRoot.attach(msgImage)
    
    # Create an smtplib.SMTP object to send the email.
    smtp = smtplib.SMTP()
    # Connect to the SMTP server.
    smtp.connect('smtp.code-learner.com')
    # Login to the SMTP server with username and password.
    smtp.login('hello', 'haha')
    # Send email with the smtp object sendmail method.
    smtp.sendmail(strFrom, strTo, msgRoot.as_string())
    # Quit the SMTP server after sending the email.
    smtp.quit()

7. Question & Answer.

7.1 How to send emails that have Html content embedded with images.

  1. I use the python email module to send some emails, and my email content is Html format with some images embedded in it. Now the image is embedded in it with the image Html tag like <img src=”../image_path/image_1.png”></img>. I know it is better to use content-id in the Html image tag src attribute, but how to implement it? Thanks.
  2. You can read the following sections of this article to learn how to do it. 1. Send HTML Content In Email. 2. Send Email With Attachments. 3. Send Email With Image.

3 thoughts on “Python Send Html, Image And Attachment Email Example”

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.