Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send an email with style in Python3?

I am sending emails from a Python3 script (using smtplib). By now, I am always receiving the messages in Gmail accounts. But the problem is I am not able to show CSS styles, in spite of being inline. Besides, even this simple message cannot be sent:

title = 'My title'
msg_content = '<h2>{title}: <font color="green">OK</font></h2>\n'.format(title=title)

However, if I remove the two points just after {title}, it works. And if I remove the \n at the end it will not work again. Why? How can I send a line like this in Python3?

title = 'My title'
msg_content = '<h2>{title}: <span style="color: green">OK</span></h2>'.format(title=title)

EDIT

import smtplib

msg_header = 'From: Sender Name <sender@server>\n' \
             'To: Receiver Name <receiver@server>\n' \
             'Cc: Receiver2 Name <receiver2@server>\n' \
             'MIME-Version: 1.0\n' \
             'Content-type: text/html\n' \
             'Subject: Any subject\n'
title = 'My title'
msg_content = '<h2>{title} > <font color="green">OK</font></h2>\n'.format(
    title=title)
msg_full = (''.join([msg_header, msg_content])).encode()

server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login('[email protected]', 'senderpassword')
server.sendmail('[email protected]',
                ['[email protected]', '[email protected]'],
                msg_full)
server.quit()
like image 863
forvas Avatar asked Jun 06 '14 08:06

forvas


People also ask

How do I send an email using Python 3?

To send the mail you use smtpObj to connect to the SMTP server on the local machine. Then use the sendmail method along with the message, the from address, and the destination address as parameters (even though the from and to addresses are within the e-mail itself, these are not always used to route the mail).

How do you send a custom email in Python?

Set up a secure connection using SMTP_SSL() and .starttls() Use Python's built-in smtplib library to send basic emails. Send emails with HTML content and attachments using the email package. Send multiple personalized emails using a CSV file with contact data.


1 Answers

Edit after clarification

The msg_full result of your example looks like this:

From: Sender Name <sender@server>
To: Receiver Name <receiver@server>
Cc: Receiver2 Name <receiver2@server>
MIME-Version: 1.0
Content-type: text/html
Subject: Any subject
<h2>My title > <font color="green">OK</font></h2>

Your E-Mail format is not conforming to RFC 2822:

  • You must use CRLF ('\r\n') as newline separators, LF (\n') only is illegal
  • Headers and body must be separated by a CRLF (i.e. one empty line). If you do a ''.join([msg_header, msg_body]), this does not insert this line. What you want to be transmitted as the body text is therefore treated as a header.

A correct version of the same email would look like this:

Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
From: Sender Name <sender@server>
To: Receiver Name <receiver@server>
Cc: Receiver2 Name <receiver2@server>
Subject: Any subject

<h2>My title > <font color="green">OK</font></h2>

I strongly encourage you to use Python's built in libraries for building RFC conformant payloads.

import smtplib
from email.mime.text import MIMEText

title = 'My title'
msg_content = '<h2>{title} > <font color="green">OK</font></h2>\n'.format(title=title)
message = MIMEText(msg_content, 'html')

message['From'] = 'Sender Name <sender@server>'
message['To'] = 'Receiver Name <receiver@server>'
message['Cc'] = 'Receiver2 Name <receiver2@server>'
message['Subject'] = 'Any subject'

msg_full = message.as_string()

server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login('[email protected]', 'senderpassword')
server.sendmail('[email protected]',
                ['[email protected]', '[email protected]'],
                msg_full)
server.quit()

In addition, it is good form to add a text/plain version of your message as well, so that any receipient can read it anywhere (I have HTML mail disabled and don't see any of that on my client). You can do that easily with email.mime.text:

from email.mime.multipart import MIMEMultipart

message = MIMEMultipart('alternative')
message['From'] = 'Sender Name <sender@server>'
message['To'] = 'Receiver Name <receiver@server>'
message['Cc'] = 'Receiver2 Name <receiver2@server>'
message['Subject'] = 'Any subject'

# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')

# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
message.attach(part1)
message.attach(part2)

Previous Answer

Your question lacks the code you are using to send the mail. I am strongly suspecting you pass msg_content directly as the message to SMTP.sendmail.

SMTP.sendmail, however transmits this string as-is, i.e. as the payload of the mail according to RFC 5321. This payload-data consists of email headers and content, with headers at the top of the message (see RFC 2822).

Your message "My title: <span..." is therefore interpreted as the Header "My title:" and not shown at the receiving end. If you remove the colon after {title}:, then the receiver obviously does not treat the result as a header, etc.

For HTML styled mail, look at the examples at https://docs.python.org/2/library/email-examples.html - basically you must create a proper text/html MIME encoded message in order to send your message.

like image 61
nd. Avatar answered Sep 19 '22 14:09

nd.