I created a relatively simple emailer class in python with the intention of reading in a CSV file and filling in a Jinja2 template with dynamic information from the CSV and then sending out emails for every row in the CSV.
I was playing around with getting it set up and I think I finally worked out all the Godaddy / Hosting quirks and am connected to the SMTP relay and can send emails.
When I sent my first email I noticed I was getting an exact duplicate copy when running the script with only "# temp.send(temp.msg("[email protected]", "Recipient"))" being actually sent (commented out in my code as I continued to debug). Something to note is that I did not properly end the connection after I was finished sending the email, I fixed that now but Godaddy has 5 email per day limit for relays on the hosting we have so I can't test exact same configuration.
Regardless, my Jinja2 template with code as is, is rendering two identical messages (both html pages no weird spacing at the end just a newline from the closing tag of the previous HTML, newline, identical opening tag) here is console output of the ending and beginning of the duplicate.
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
The dynamic content is being filled in properly on both console outputs and the content when sent to a test email looked proper besides some poor formatting in the HTML (dynamic content was filled, header info correct).
My questions are:
I searched for this problem found a StackOverflow post with no answer: Sending email with Python and smtplib getting two duplicate emails
I don't know if this person debugged their template to see what it was rendering though.
from jinja2 import *;
import os
from os.path import join, dirname
from dotenv import load_dotenv
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
#Adding .env to path
dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)
#Emailer Class that loads in templates and config, and handles data parsing.
class Emailer:
#Load template and set subject
env = Environment(
loader=PackageLoader('email-lib')
)
template = env.get_template("email-template.html")
subject = os.environ.get("SUBJECT")
# Mail can't be sent while not connected.
connected = False
#Init
def __init__(self):
self.ourEmail = os.environ.get("EMAIL")
self.password = os.environ.get("PASS")
self.server = smtplib.SMTP(os.environ.get("SERVER"))
#Testing Render
def print(self, name):
print(self.template.render(recipientName = name))
#Returning render without needing to get acess to public template
def render(self, name):
return self.template.render(recipientName = name)
#Generating plain text body with desired content
def msg(self, toEmail, recipient):
msg = MIMEMultipart('alternative')
msg["From"] = self.ourEmail
msg["To"] = toEmail
msg["Subject"] = self.subject
# msg.attach(MIMEText(self.render(recipient),'plain'))
msg.attach(MIMEText(self.render(recipient), 'html'))
return msg
#Connect and login to SMTP server
def startConnect(self):
self.connected = True
self.server.starttls()
self.server.login(self.ourEmail,self.password)
#Send to the smtp server
def send(self, msg):
if self.connected:
self.server.sendmail(msg["From"], msg["To"], msg.as_string())
else:
raise ConnectionAbortedError("Emailer is not connected to an email server but a message attempted to send.")
#Stop server connection when finished.
def stop(self):
self.connected = False
self.server.quit()
temp = Emailer()
# print(temp.msg("[email protected]", "Recipient"))
print(temp.template.render(recipientName = "Test"))
# temp.startConnect()
# temp.send(temp.msg("[email protected]", "Recipient"))
# temp.stop()
It was an issue with the imports and leaving code around outside main.
Wrapping the execution portion in a main function fixed it:
if __name__ == '__main__':
#Adding .env to path
dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)
temp = Emailer()
# print(temp.msg("[email protected]", "Recipient"))
temp.startConnect()
temp.send(temp.msg("[email protected]", "test"))
temp.stop()