Search code examples
pythonsmtplib

How to combine .decode('utf-8') and .format() in Python?


I'm trying to send an email in Python that will be both encoded in UTF-8 and will have a formatting (so each client will be greeted with his name etc.).

Here's my function responsible for sending email, simplified:

def sendMail(recipient, recipientName):
    file = open('~/mail.txt'.format(name), 'r')
    data = file.read()
    msg = MIMEText(data.decode('utf-8'), 'html', 'utf-8') # <<<<
    file.close()
    mail = smtplib.SMTP_SSL(ip, port)
    mail.login(mailUser, mailPassword)
    mail.sendmail(mailHost, recipient, msg.as_string().format(recipientName)) # <<<<
    mail.quit()

And this is the content of mail.txt file.

Basically the relevant thing here are 3rd and 7th lines of function - the rest is related to mail sending and is working fine. If I don't use .decode('utf-8'), formatting is fine - but in turn the email is almost unreadable.

I tried % parameters and f parameters as well with no success - basically only .format doesn't pull any error besides not actually working.


Solution

  • Applying .format() to msg.as_string() seems extremely brittle. At this point, msg should contain a properly MIME-encoded message which might not contain your format strings at all any longer (for example, if the content requires base64 encoding, it will not look at all like your input). Apply the formatting at an earlier point in the process.

    def sendMail(recipient, recipientName):
        with open('~/mail{0}.txt'.format(name), 'r', encoding='utf-8') as file:
            data = file.read()
            msg = MIMEText(data.format(recipientName), 'html', 'utf-8')
        mail = smtplib.SMTP_SSL(ip, port)
        mail.login(mailUser, mailPassword)
        mail.sendmail(mailHost, recipient, msg.as_string())
        mail.quit()