Send SMTP email with Python (using SMTPLib)
How to send emails with Python's built-in SMTP client and MailSlurp mail servers. Idiomatic Python mail configuration and sending.
Python is the language that can do it all - including SMTP email! Using the in-built smtplib
library we can setup outbound email sending in Python to external SMTP servers. Let us demonstrate.
What is SMTP and how does it work?
Firstly, a quick overview of SMTP and how emails work. SMTP (simple mail transfer protocol) describe the sending and receiving of email over TCP - typically on the ports 25, 2525, 465 or 587. Each email address (such as @gmail.com) has an underlying SMTP server that runs on the domain (smtp.gmail.com for instance) and listens for incoming emails. When we wish to email an address provided by the server we can connect via SMTP in Python and submit a message.
Configuring SMTPLib
To use Python to send SMTP emails we first need to import and configure the batteries included smtplib
library. In a new python file add:
from smtplib import SMTP
Once imported you can open a new connection like so:
with SMTP(host='smtp.gmail.com', port=465) as smtp:
smtp.sendmail(from_addr='from@address.com', to_addrs=['to@address.com'], msg='Your message')
smtp.quit()
For each email you wish to send you will need to connect to the underlying SMTP server or use your own SMTP server to pass the emails on for you. When using your own SMTP server you will want to create authentication so that only you can send from it.
Using authentication
Say you have created an SMTP server with MailSlurp, you can access the server using your username and password for the account hosted on a domain and port:
Protocol | Host | Port | TLS | Description |
---|---|---|---|---|
SMTP | mx.mailslurp.com | 2525 | false | SMTP server |
In code you can use the MailSlurp SDK to obtain these details with the inbox_controller.get_imap_smtp_access()
method.
# get smtp imap access
smtp_access = inbox_controller.get_imap_smtp_access(inbox_id=inbox1.id)
msg = "Subject: Test subject\r\n\r\nThis is the body"
with SMTP(host=smtp_access.smtp_server_host, port=smtp_access.smtp_server_port) as smtp:
smtp.login(user=smtp_access.smtp_username, password=smtp_access.smtp_password)
smtp.sendmail(from_addr=inbox1.email_address, to_addrs=[inbox2.email_address], msg=msg)
smtp.quit()
SMTP servers provide several authentication methods but LOGIN
and PLAIN
are two common methods.
Sending email content
To send SMTP emails in Python you must construct and email body. The body of an email begins with lines of headers that are key value pairs and then a body separated by a new line. For instance: msg = "Subject: Test subject\r\n\r\nThis is the body"
.
Testing emails with MailSlurp
To test if your Python application is sending emails correctly or to run your own SMTP server try MailSlurp. MailSlurp provides unlimited disposable (or permanent) email mailboxes that can be connected to using Python and SMTP to send emails. Let us use MailSlurp and Pytest to demonstrate:
import os
# get an api key at https://app.mailslurp.com/sign-up
import mailslurp_client
from smtplib import SMTP
from mailslurp_client import CreateInboxDto
api_key = os.environ.get('API_KEY')
assert api_key is not None
# create a mailslurp configuration
configuration = mailslurp_client.Configuration()
configuration.api_key['x-api-key'] = api_key
class Test_MailSlurp_SDK:
"""
Can send email with SMTP
"""
def test_can_send_with_smtp(self):
with mailslurp_client.ApiClient(configuration) as api_client:
inbox_controller = mailslurp_client.InboxControllerApi(api_client)
inbox1 = inbox_controller.create_inbox_with_options(CreateInboxDto(inbox_type="SMTP_INBOX"))
inbox2 = inbox_controller.create_inbox()
assert "@mailslurp.mx" in inbox1.email_address
# get smtp imap access
smtp_access = inbox_controller.get_imap_smtp_access(inbox_id=inbox1.id)
msg = "Subject: Test subject\r\n\r\nThis is the body"
with SMTP(host=smtp_access.smtp_server_host, port=smtp_access.smtp_server_port) as smtp:
smtp.login(user=smtp_access.smtp_username, password=smtp_access.smtp_password)
smtp.sendmail(from_addr=inbox1.email_address, to_addrs=[inbox2.email_address], msg=msg)
smtp.quit()
wait_for_controller = mailslurp_client.WaitForControllerApi(api_client)
email = wait_for_controller.wait_for_latest_email(inbox_id=inbox2.id)
assert "Test subject" in email.subject
More information
To read more about SMTP email sending in Python consult the smtplib docs or see the MailSlurp Python developer page.