Search code examples
pythonpython-3.xstringvariablesmime

Importing text and html template for e-mail correctly


I'm working on code to automate survey participation requests. My current code looks as follows:

def survey_mail(name, receiver, sender):
    
    text_content = f"Hello {name},\r\n
             Thank you for participating in my survey via your mail {receiver}\r\n.
             You can contact me via {sender}."
    
    html_content = """\ Hello """ + str(name) + """,<br>
             Thank you for participating in my survey via your mail """ + str(receiver) + """<br>.
             You can contact me via """ + str(sender) + """.
           """

    content = MIMEMultipart('alternative')
    content.attach(MIMEText(text_content, 'plain'))
    content.attach(MIMEText(html_content, 'html'))
    ...

I have two questions here:

  1. First, would it be possible to import the two string above simply as template files?
  2. Second, is there a better way to handle variables in the string? The current method comes with two different ways to format variables: {} vs. """ + var + """.

I tried to insert the two templates as *.txt files, and then load the templates:

with open("text.txt") as f:
    text_content = f.read()

with open("html.txt") as f:
    html_content = f.read()

However, this did not work. The code does just import the template as a full string.


Solution

  • f-strings are evaluated are definition time, so you cannot read them from a file. The second way in your example (for html) is an expression. While an expression can be eval-ed, it is generally seen as a poor security practice, because it allows execution of uncontrolled code.

    But you could just use format as a poor man's templating engine: it have far less features that full fledged template engines, but is enough here.

    Example file for the text part:

    Hello {name},
    
    Thank you for participating in my survey via your mail {receiver}.
    
    You can contact me via {sender}.
    

    You can then use it that way:

    with open("text.txt") as f:
        text_content = f.read().format(sender=sender, receiver=receiver)