The following will be covered in this article :
-
setup a secure connection using smtps or starttls
-
use smtplib to send plain-text email
-
use the email package to define mime objects for sending emails formatted in html
Setting up a local smtp debug server
To test the code you could use the available python smtpd binary, bind it to port 1025 since the messages won't cross over our localhost, otherwise, we'd use ports 587 or 2525 and 465 depending upon how the message is encrypted. All the messages submitted to port 1025 would be outputted to stdout as a byte stream.
python -m smtpd -c DebuggingServer -n localhost:1025
Starting a secure smtp connection
Note: It isn't necessary to secure your messages when using a local debugging server
As mentioned above, there are 2 ways to secure your messages, using smtps and starttls
- Start an SMTP connection that is secured from the beginning using
SMTP_SSL()
- Start an unsecured SMTP connection that can then be encrypted using
.starttls()
We'll be employing python's smtplib package to secure our messages using the above 2 methods.
We'll also use the ssl package to load the default trusted ca bundles of our system/environment, this'll be achieved by create_default_context() method.
Below are the code examples of both the methods mentioned above, we'll be using the gmails smtp server in our examples hereon.
#using smtps to secure the connection from the outset
import smtplib, ssl
port = 465 # For SSL
password = input("Input password and press enter: ")
# Create a secure SSL context, loads system's default trusted CAs
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", port, context=context) as server:
server.login("my@gmail.com", password)
#using starttls to secure the connection from a point onwards
import smtplib, ssl
smtp_server = "smtp.gmail.com"
port = 587 # For starttls
sender_email = "my@gmail.com" # Enter your address
password = input("Input password and press enter: ")
# Create a secure SSL context, loads system's default trusted CAs
context = ssl.create_default_context()
# Try block
try:
server = smtplib.SMTP(smtp_server,port)
server.ehlo() # Can be omitted, called implicitly by the method if required
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted, called implicitly by the method if required
server.login(sender_email, password)
# TODO: Send email here
except Exception as e:
# Print any error messages to stdout
print(e)
finally:
server.quit()
Let's start with sending a plain text email
We'll employ server.sendmail to send our emails, I'll be using the as server directive in my examples below
Define the email addresses and the message body at the beginning of your script rather than defining them inside the method, such as
sender_email = "my@gmail.com" # Enter your address
receiver_email = "your@gmail.com" # Enter receiver address
message = """\
Subject: Hi there
Your email body goes here (please note: 2 newlines follow the subject)"""
Example to send a plain text email secured using smtps
import smtplib, ssl
port = 465 # For SSL
smtp_server = "smtp.gmail.com"
sender_email = "my@gmail.com" # Enter your address
receiver_email = "your@gmail.com" # Enter receiver address
password = input("Input password and press enter: ")
message = """\
Subject: Hi there
Message body after 2 new lines."""
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
Example to send a plain text email secured using starttls
import smtplib, ssl
port = 587 # For starttls
smtp_server = "smtp.gmail.com"
sender_email = "my@gmail.com" # Enter your address
receiver_email = "your@gmail.com" # Enter receiver address
password = input("Input password and press enter:")
message = """\
Subject: Hi there
Message body after 2 new lines."""
context = ssl.create_default_context()
with smtplib.SMTP(smtp_server, port) as server:
server.ehlo() # Can be omitted, called implicitly by the method if required
server.starttls(context=context)
server.ehlo() # Can be omitted, called implicitly by the method if required
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
Sending emails structured with html content or having packages
What is MIME ? Just like how a byte stream is structured into IP packets and ethernet frames conforming to the different layers of the internet, MIME is an encapsulation used at the application level, it is basically an extension of SMTP. We'll be using MIME multipart email to achieve formatting emails combining HTML and plain ascii text. This would be handled by the python email.mime module.
Since we are combining both HTML and ascii text in our MIME data structures, and since as per the design, the email client will render the last MIME part first, we'd add HTML after the plain text.
Example to send a mail distributed using MIME
import smtplib, ssl
from email.mime.text import MIMEText # this object contains the html and ascii content
from email.mime.multipart import MIMEMultipart # this is where we combine the two
sender_email = "my@gmail.com" # Enter your address
receiver_email = "your@gmail.com" # Enter receiver address
password = input("Input password and press enter: ")
message = MIMEMultipart("alternative")
message["Subject"] = "multipart test"
message["From"] = sender_email
message["To"] = receiver_email
# Create the plain-text and HTML version of your message
text = """\
Hi,
How are you?
html = """\
<html>
<body>
<p>Hi,<br>
How are you?<br>
</p>
</body>
</html>
"""
# Convert these into MIMEText objects
text1 = MIMEText(text, "plain")
html1 = MIMEText(html, "html")
# Add the objects to MIMEMultipart object
# The email client render the last part first, hence we add html part last
message.attach(text1)
message.attach(text2)
# Create secure connection with server and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(sender_email, password)
server.sendmail(
sender_email, receiver_email, message.as_string()
)
Certain unknowns that we'd need to define in the py script :-
(Per below, I'm assuming that the SMTP server for the deployment is AWS SES, please amend as per your deployments SMTP host)
- smtp host : value is the server name on the smtp settings page; smtp settings page can be reached via ses service page
- smtp username and Passwd : these values need to be created from the smtp settings page via the function/button "Create My SMTP Credentials"
- Please note that these values should be available from Domino central config, if not, they must be populated as central config key value pairs. For more information regarding your deployment's central config, please reach out to the internal Domino admin.
Comments
0 comments
Please sign in to leave a comment.