6

I'm using information found on this post Sending Email Using Python

So far the instructions were perfect. I have two additional things I'd like to do:

  1. Call a variable inside the body
  2. Add an attachment

The variable would be todays date. This is it:

today = datetime.datetime.today ()
tday = today.strftime ("%m-%d-%Y")

I know that with mailx, you can attach with the -a option.

4
  • Can't you just put the stringified date in the body? Commented Jan 25, 2017 at 17:14
  • Could you share your current code so we can try to find whats missing? Commented Jan 25, 2017 at 17:35
  • 1
    "Call a variable"? You mean insert a variable? Use a template library (or just string formatting) to produce a document to mail. Commented Jan 25, 2017 at 17:43
  • There's a wide list of template engines given at wiki.python.org/moin/Templating#Templating_Engines; using an XML-aware option such as Genshi is strongly preferable from a security perspective. Commented Jan 25, 2017 at 18:04

3 Answers 3

12

To call the variables inside the html body ,just convert them to string to concatenate them in the body

from datetime import datetime
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

today = datetime.today ()
tday = today.strftime ("%m-%d-%Y")

# email subject, from , to will be defined here
msg = MIMEMultipart()

html = """\
<html>
  <head></head>
  <body>
    <p>Hi!<br>
       How are you?<br>
       """ +str(today)+ """ and """ +str(tday)+ """
    </p>
  </body>
</html>
"""
msg.attach(MIMEText(html, 'html'))

For attachments please look at http://naelshiab.com/tutorial-send-email-python/

EDIT : The link provided above seems not available, so the code snippet for sending attachments via email (specifically from gmail) is below

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

msg = MIMEMultipart()

msg['From'] = "from email address"
msg['To'] = "to email address" 
msg['Subject'] = "Subject line" 
body = """Body 
          content"""

msg.attach(MIMEText(body, 'plain'))
attachment = open("/path/to/file", "rb") 
p = MIMEBase('application', 'octet-stream') 

# To change the payload into encoded form 
p.set_payload((attachment).read()) 

# encode into base64 
encoders.encode_base64(p) 

p.add_header('Content-Disposition', "attachment; filename= %s" % filename) 

# attach the instance 'p' to instance 'msg' 
msg.attach(p) 

s = smtplib.SMTP('smtp.gmail.com', 587) 
s.starttls() # for security
s.login("from email address", "your password") 

text = msg.as_string() 

# sending the mail 
s.sendmail("from email address", "to email address" , text)
s.quit() 

Note : Google will some times block logins from other application (less secure apps) so there is a need to allow this access in your Google account settings https://myaccount.google.com/u/1/lesssecureapps?pli=1&pageId=none

Sign up to request clarification or add additional context in comments.

3 Comments

This is only sound advice if the values are trusted. If they include, say, <script> content, this won't perform proper escaping to ensure that the inserted content is viewed as text rather than rendered by the browser.
is it possible to read HTML from *.html template to the Python script with variables automatically being placed in the code?
Is it possible to use fstrings inside the HTML snippet that you have shared above in the code?
0

For your first question: There are lots of ways to create strings that make use of variables.

Some ways are:

body = "blablabla " + tday + " bloo bloo bloo"
body = "Today's date is {}, in case you wondered".format(tday)

For your second question you'd have to tell us which library / module you're using, and then you could go to that module's documentation page and see if there's something for adding an attachment.

4 Comments

The best-practice approach here from a security-perspective will be a formatting-aware toolset that can prevent injection attacks (in this context, a category wherein content that is expected to be providing literal text for rendering to the user instead acts as an instruction to the browser).
Oh yeah that's totally true. In this case OP's question didn't mention user-input from a form, so I didn't think about it. Basically, if you have control over the string and what goes in (e.g. a specifically formatted date string), you don't really have to worry about injection, right?
Yup. Thing is, an answer to a question as "how do I use a variable inside HTML email?" is likely to be applied in a wider range of scenarios than just the one contrived example given in the question.
To send to multiple recipients, I used the info from stackoverflow.com/questions/8856117/…
0

Thanks to everyone for posting tips.

For posterity, this is the working script.

The only remaining item is that I need to be able to send the same email to multiple people.

I've tried to add all of the email addresses to the variable with commas between, but they're not getting it. When I look at my email received, they appear to be in the To line. Is it possible that it's only sending to the first email address listed?

#!/usr/bin/python
import smtplib
import time
import datetime
from datetime import date
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase
from email import encoders

fromaddr = "[email protected]"
toaddr = ['[email protected]', '[email protected]']

#   Date
today = datetime.datetime.today ()
tday = today.strftime ("%m-%d-%Y")

msg = MIMEMultipart()

msg['From'] = fromaddr
msg['To'] = ", ".join(toaddr)
msg['Subject'] = "My Subject Goes Here"

body = """\
<html>
  <head></head>
  <body>
<p>DO NOT REPLY TO THIS EMAIL!!<br>
<br>
Script run for data as of """ + tday + """.<br>
<br>
See attachment for items to discuss<br>
<br>
The files have also been uploaded to <a href="http://testing.com/getit">SharePoint</a><br>
<br>
If you have any issues, email [email protected]<br>
<br>
    </p>
  </body>
</html>
"""

msg.attach(MIMEText(body, 'html'))

filename = "discuss.csv"
attachment = open("discuss.csv", "rb")

part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)

msg.attach(part)

server = smtplib.SMTP('localhost')
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.