{"id":24699,"date":"2026-01-15T13:06:37","date_gmt":"2026-01-15T13:06:37","guid":{"rendered":"https:\/\/www.mailgun.com\/blog\/envoyer-email-avec-python\/"},"modified":"2026-09-16T19:09:16","modified_gmt":"2026-09-16T19:09:16","slug":"envoyer-email-avec-python","status":"publish","type":"blog","link":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/","title":{"rendered":"Envoyer des emails avec Python3 et l&rsquo;API de Mailgun"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">If you\u2019re looking to streamline your approach to programmatically sending email, you\u2019re in good hands. Our developers have the experience you need to get started. Read on as we delve into the details of integrating Python3 with Mailgun\u2019s robust email API, with insights, guidance, and optimizations along the way.<\/p>\n\r\n    <nav data-content-type=\"longform\" class=\"toc-block longform-spacings px-5 py-6 px-md-6 px-lg-7 py-md-7 bg-light fs-sm rounded-lg\" aria-labelledby=\"toc-title-4715\"><p class=\"h5 m-0\" id=\"toc-title-4715\">Table des mati\u00e8res<\/p><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">01<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#getting-started-what-youll-need-for-this-tutorial\">Getting started: What you\u2019ll need for this tutorial<\/a><a class=\"scrollme link-body-color\" href=\"#prerequisites\">Prerequisites<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">02<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#setting-up-a-new-python-project\">Setting up a new Python project<\/a><a class=\"scrollme link-body-color\" href=\"#obtaining-an-api-key-with-mailgun\">Obtaining an API key with Mailgun<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">03<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#imports-and-initialization\">Imports and initialization<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">04<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#sending-single-emails-using-the-mailgun-api\">Sending single emails using the Mailgun API<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">05<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#sending-bulk-email-with-the-mailgun-api\">Sending bulk email with the Mailgun API<\/a><a class=\"scrollme link-body-color\" href=\"#how-can-i-send-multiple-personalized-emails\">How can I send multiple personalized emails?\u00a0<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">06<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#additional-features-of-mailguns-email-api\">Additional features of Mailgun&rsquo;s email API<\/a><a class=\"scrollme link-body-color\" href=\"#sending-html-emails-with-attachments\">Sending HTML emails with attachments<\/a><a class=\"scrollme link-body-color\" href=\"#email-delivery-and-tracking\">Email delivery and tracking<\/a><a class=\"scrollme link-body-color\" href=\"#email-templates\">Email templates<\/a><a class=\"scrollme link-body-color\" href=\"#email-testing\">Email testing\u00a0<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">07<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#alternative-python-email-libraries\">Alternative Python email libraries\u00a0<\/a><a class=\"scrollme link-body-color\" href=\"#smtplib\">smtplib\u00a0<\/a><a class=\"scrollme link-body-color\" href=\"#yagmail\">Yagmail\u00a0<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">08<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#authentication-and-security\">Authentication and security\u00a0<\/a><a class=\"scrollme link-body-color\" href=\"#error-handling\">Error handling\u00a0<\/a><a class=\"scrollme link-body-color\" href=\"#email-deliverability\">Email deliverability\u00a0<\/a><a class=\"scrollme link-body-color\" href=\"#authenticate-your-email\">Authenticate your email\u00a0<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">09<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#start-sending-with-python3-and-mailguns-email-api\">Start sending with Python3 and\u00a0Mailgun&rsquo;s\u00a0Email API<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">10<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#faqs\">FAQs<\/a><\/div><\/div><\/nav>\n<h2 class=\"wp-block-heading\">Getting started: What you\u2019ll need for this tutorial<\/h2>\n\n<p class=\"wp-block-paragraph\">When sending email, you have two choices, manual, or programmatic. When we\u2019re talking about <a href=\"https:\/\/www.mailgun.com\/blog\/email\/what-is-transactional-email-basics\/\" target=\"_tabs\" rel=\"noopener noreferrer\">transactional emails<\/a> specifically, programmatic is the way to go. Instead of sending important email updates or notifications manually, you can use automated email scripts to save time and reduce errors.<\/p>\n\n<p class=\"wp-block-paragraph\">Scripts \u2014 small programs that automate tasks \u2014 offer a more efficient way to send bulk emails, schedule messages, or get called directly from your application. Some use cases for sending emails through automated scripts include the following:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Sending welcome emails for user registration<\/li>\n\n\n\n<li>Sending notifications and alerts from applications, such as informing users about their service usage or notifying admins when server resources are running low<\/li>\n\n\n\n<li>Sending reports, such as a weekly new customer report<\/li>\n\n\n\n<li>Sending marketing campaigns \u2013 for instance, to promote new products or services<\/li>\n<\/ul>\n\n<p class=\"wp-block-paragraph\">In this tutorial, you&rsquo;ll learn how to send emails using Python3 scripts and the Mailgun API.<\/p>\n\n<h3 class=\"wp-block-heading\">Prerequisites<\/h3>\n\n<p class=\"wp-block-paragraph\">To follow along with this Python3 and email API tutorial, you&rsquo;ll need the following:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Python 3.9 or higher. Python is often described as the Swiss Army knife of programming languages, and it offers a wide range of capabilities. In addition to its many other uses, Python is great for writing various scripts.<\/li>\n\n\n\n<li>A Mailgun account. Mailgun is an email-sending platform that lets you send and track emails. <!-- -->If you aren&rsquo;t already a Mailgun user, you can follow along with this tutorial using <a href=\"https:\/\/signup.mailgun.com\/new\/signup\" target=\"_tabs\" rel=\"noopener noreferrer\">our free trial<\/a>.<\/li>\n<\/ul>\n\n<h2 class=\"wp-block-heading\">Setting up a new Python project<\/h2>\n\n<p class=\"wp-block-paragraph\">Let\u2019s dive in.<\/p>\n\n<p class=\"wp-block-paragraph\">Start by creating a suitable directory for your Python project and add an empty .env file inside it. Before proceeding, consider creating and activating a new <a href=\"https:\/\/docs.python.org\/3\/library\/venv.html\" target=\"_tabs\" rel=\"noopener noreferrer\">virtual environment<\/a> before installing the Python libraries required for this tutorial. It isolates your project, which prevents any dependency conflicts.<\/p>\n\n<p class=\"wp-block-paragraph\">To install the necessary libraries (requests and python-dotenv) using pip in your virtual environment, run the following command:<\/p>\n\n<p class=\"wp-block-paragraph\">pip install requests python-dotenv<\/p>\n\n<p class=\"wp-block-paragraph\">The requests library allows you to make API calls, while the python-dotenv library allows you to store the API key outside your code.<\/p>\n\n<h3 class=\"wp-block-heading\">Obtaining an API key with Mailgun<\/h3>\n\n<p class=\"wp-block-paragraph\">Next, you&rsquo;ll obtain an API key from your Mailgun account, which you&rsquo;ll use to make API calls to Mailgun.<\/p>\n\n<p class=\"wp-block-paragraph\">Sign in to your Mailgun account and create an API key from the <a href=\"https:\/\/app.mailgun.com\/settings\/api_security\" target=\"_tabs\" rel=\"noopener noreferrer\">API Security page<\/a>, which is accessible via a drop-down below your name in the top right corner.<\/p>\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4967\" width=\"1208\" height=\"732\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screenshot_2024-05-15_at_8.20.19_PM.png\" alt=\"New API key location in Mailgun\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screenshot_2024-05-15_at_8.20.19_PM.png 1208w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screenshot_2024-05-15_at_8.20.19_PM-300x182.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screenshot_2024-05-15_at_8.20.19_PM-768x465.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screenshot_2024-05-15_at_8.20.19_PM-1024x621.png 1024w\" sizes=\"(max-width: 1208px) 100vw, 1208px\" \/><\/figure>\n\n<p class=\"wp-block-paragraph\">Copy and paste this API key into your project&rsquo;s .env file.<\/p>\n\n<p class=\"wp-block-paragraph\">MAILGUN_API_KEY=\u00a0\u00bbYour API Key Here\u00a0\u00bb<\/p>\n\n<p class=\"wp-block-paragraph\">While you&rsquo;re in Mailgun, note down your sending domains from the Mailgun dashboard.<\/p>\n\n<p class=\"wp-block-paragraph\">If you&rsquo;re on a free plan, you will see a sandbox domain, which will be used in the API endpoint as well as for the from email address when sending emails through the Mailgun API. The sandbox domain follows the format &lt;your-sandbox-id&gt;.<a href=\"http:\/\/mailgun.org\/\" target=\"_tabs\" rel=\"noopener noreferrer\">mailgun.org<\/a>, as shown below.<\/p>\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4968\" width=\"1392\" height=\"194\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image2-4.png\" alt=\"Sandbox domain in Mailgun\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image2-4.png 1392w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image2-4-300x42.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image2-4-768x107.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image2-4-1024x143.png 1024w\" sizes=\"(max-width: 1392px) 100vw, 1392px\" \/><\/figure>\n\n<p class=\"wp-block-paragraph\">You will need to upgrade to a paid plan if you need to use a custom email domain for sending emails through Mailgun. The free plan only allows the sandbox domain, and you can send emails to a maximum of five verified addresses. However, this free plan is useful during the development phase when integrating the Mailgun API into your system.<\/p>\n\n<h2 class=\"wp-block-heading\">Imports and initialization<\/h2>\n\n<p class=\"wp-block-paragraph\">Next, create the file main.py in your project directory and copy and paste this code:<\/p>\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                Python                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-Python\">\r\n                                <code id=\"code_0_content\" class=\"language-Python\">\r\n\r\n                                    ```python import jsonrnimport requestsrnimport loggingrnrnimport osrnfrom dotenv import load_dotenvrnrnlogging.basicConfig(level=logging.INFO) # set log levelrnload_dotenv() # for reading API key from `.env` file.rnrn# Sandbox API URL format: https:\/\/api.mailgun.net\/v3\/sandbox&lt;ID&gt;.mailgun.org\/messagesrnMAILGUN_API_URL = &quot;https:\/\/api.mailgun.net\/v3\/YOUR_DOMAIN_NAME\/messages&quot;rnFROM_EMAIL_ADDRESS = &quot;Sender Name &lt;SENDER_EMAIL_ID&gt;&quot;\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n<p class=\"wp-block-paragraph\">It uses Python&rsquo;s standard logging and configures it to INFO level with this code:<\/p>\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                Python                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-Python\">\r\n                                <code id=\"code_0_content\" class=\"language-Python\">\r\n\r\n                                    ```pythonrnlogging.basicConfig(level=logging.INFO)rn```\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n<p class=\"wp-block-paragraph\">The load_dotenv() function comes from the python-dotenv library and is used to load environment variables from the .env file in your Python code. It is a good practice to store and read sensitive information such as credentials and API keys from the .env file.<\/p>\n\n<p class=\"wp-block-paragraph\">MAILGUN_API_URL sets the API URL for your Python script, and indicates the sender&rsquo;s email ID. Both must use your email sending domain or the sandbox domain mentioned earlier.<\/p>\n\n<h2 class=\"wp-block-heading\">Sending single emails using the Mailgun API<\/h2>\n\n<p class=\"wp-block-paragraph\">Let&rsquo;s first look at the most simple way of using Mailgun API: sending a single email. You can use it for one-off cases, like sending a reminder or a follow-up email to your high-value customer. This will allow you to track the email delivery as well.<\/p>\n\n<p class=\"wp-block-paragraph\">Copy and paste the code below into your main.py file after the imports and initialization:<\/p>\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                Python                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-Python\">\r\n                                <code id=\"code_0_content\" class=\"language-Python\">\r\n\r\n                                    ```pythonrndef send_single_email(to_address: str, subject: str, message: str):rn\u00a0\u00a0\u00a0\u00a0try:rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0api_key = os.getenv(&quot;MAILGUN_API_KEY&quot;)\u00a0 # get API-Key from the `.env` filernrn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resp = requests.post(MAILGUN_API_URL, auth=(&quot;api&quot;, api_key),rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data={&quot;from&quot;: FROM_EMAIL_ADDRESS,rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&quot;to&quot;: to_address, &quot;subject&quot;: subject, &quot;text&quot;: message})rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if resp.status_code == 200:\u00a0 # successrn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logging.info(f&quot;Successfully sent an email to &#039;{to_address}&#039; via Mailgun API.&quot;)rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else:\u00a0 # errorrn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logging.error(f&quot;Could not send the email, reason: {resp.text}&quot;)rnrn\u00a0\u00a0\u00a0\u00a0except Exception as ex:rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logging.exception(f&quot;Mailgun error: {ex}&quot;)rnrnif __name__ == &quot;__main__&quot;:rn\u00a0\u00a0\u00a0\u00a0send_single_email(&quot;Manish &lt;manish@exanple.com&gt;&quot;, &quot;Single email test&quot;, &quot;Testing Mailgun API for a single email&quot;)rn```\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n<p class=\"wp-block-paragraph\">This <b>send_single_email(&#8230;) <\/b>function takes three arguments: <b>to_address<\/b>, <b>subject<\/b>, and<b> message<\/b>. <b>to_address<\/b> is for a single email address, and the other two are for the email&rsquo;s subject and content.<\/p>\n\n<p class=\"wp-block-paragraph\">The code reads the Mailgun API key from the .env file and uses it to make an API call, establishing\u00a0a secure connection to the specified API_URL. This API key acts as a unique identifier, allowing Mailgun to authenticate the API call and verify who is using its services.<\/p>\n\n<p class=\"wp-block-paragraph\">You must use your unique API key to ensure proper authentication. The from email address used in this API call must also be associated with your valid domain or Mailgun&rsquo;s sandbox domain. If it doesn&rsquo;t, the call will fail with an error message.<\/p>\n\n<p class=\"wp-block-paragraph\">The data parameters are sent via HTTP POST method to the API endpoint with the requests.post(&#8230;) call.<\/p>\n\n<p class=\"wp-block-paragraph\">When the API call is successful, your email will be queued for delivery, and the API will return an HTTP-200 (OK) status. In case of an error, the API will return an error message with an appropriate HTTP status code. Both cases are appropriately logged by this code snippet.<\/p>\n\n<p class=\"wp-block-paragraph\">if __name__ == \u00ab\u00a0__main__\u00a0\u00bb shows how this function can be called in your script.<\/p>\n\n<p class=\"wp-block-paragraph\">Running this script in your terminal will show the following:<\/p>\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4969\" width=\"800\" height=\"160\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/undefined_-_Imgur.gif\" alt=\"Python script running in terminal\" \/><\/figure>\n\n<h2 class=\"wp-block-heading\">Sending bulk email with the Mailgun API<\/h2>\n\n<p class=\"wp-block-paragraph\">While you can use the send_single_email(&#8230;) function in a loop to send emails to multiple recipients, it&rsquo;s not the most efficient method due to network I\/O delays. This approach may also encounter <a href=\"text=In%2520email%2520terms%252C%2520rate%2520limiting,send%2520during%2520that%2520time%2520frame.\" target=\"_tabs\" rel=\"noopener noreferrer\">API rate limiting.<\/a><\/p>\n\n<p class=\"wp-block-paragraph\">Instead, use <a href=\"https:\/\/documentation.mailgun.com\/docs\/mailgun\/user-manual\/sending-messages\/#batch-sending\" target=\"_tabs\" rel=\"noopener noreferrer\">Batch Sending<\/a> for sending emails to multiple recipients. The code snippet below demonstrates how to use it in your Python script.<\/p>\n\n<p class=\"wp-block-paragraph\">Copy and paste the send_batch_emails(&#8230;) function into your main.py file after the send_single_email(&#8230;) function, and modify the __main__ part as shown below:<\/p>\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                Python                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-Python\">\r\n                                <code id=\"code_0_content\" class=\"language-Python\">\r\n\r\n                                    ```pythonrndef send_batch_emails(recipients: dict, subject: str, message: str):rn\u00a0\u00a0\u00a0\u00a0try:rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0api_key = os.getenv(&quot;MAILGUN_API_KEY&quot;)\u00a0 # get API-Key from the `.env` filernrn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0to_address = list(recipients.keys())\u00a0 # get only email addressesrn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0recipients_json = json.dumps(recipients)\u00a0 \u00a0 # for API callrnrn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logging.info(f&quot;Sending email to {len(to_address)} IDs...&quot;)rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resp = requests.post(MAILGUN_API_URL, auth=(&quot;api&quot;, api_key),rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data={&quot;from&quot;: FROM_EMAIL_ADDRESS,rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&quot;to&quot;: to_address, &quot;subject&quot;: subject, &quot;text&quot;: message,rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&quot;recipient-variables&quot;: recipients_json})rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if resp.status_code == 200:\u00a0 # successrn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logging.info(f&quot;Successfully sent email to {len(recipients)} recipients via Mailgun API.&quot;)rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else: \u00a0 # errorrn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logging.error(f&quot;Could not send emails, reason: {resp.text}&quot;)rn\u00a0\u00a0\u00a0\u00a0except Exception as ex:rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logging.exception(f&quot;Mailgun error: {ex}&quot;)rnrnif __name__ == &quot;__main__&quot;:rn\u00a0\u00a0\u00a0\u00a0# send_single_email(&quot;Manish &lt;manish@exanple.com&gt;&quot;, &quot;Single email test&quot;, &quot;Testing Mailgun API for a single email&quot;)rn\u00a0\u00a0\u00a0\u00a0_recipients = {&quot;manish@example.com&quot;: {&quot;name&quot;: &quot;Manish&quot;, &quot;id&quot;: 1},rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&quot;jakkie@example.com&quot;: {&quot;name&quot;: &quot;Jakkie&quot;, &quot;id&quot;: 2},rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&quot;elzet@example.com&quot;: {&quot;name&quot;: &quot;Elzet&quot;, &quot;id&quot;: 3}}rnrn\u00a0\u00a0\u00a0\u00a0send_batch_emails(_recipients, &quot;Hi, %recipient.name%!&quot;, &quot;Testing Mailgun API. This email is sent via Mailgun API.&quot;)rn```\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n<h3 class=\"wp-block-heading\">How can I send multiple personalized emails?\u00a0<\/h3>\n\n<p class=\"wp-block-paragraph\">Batch Sending uses a special parameter called Recipient Variables that lets you send personalized emails to multiple recipients in a single API call. Using Recipient Variables with Batch Sending ensures Mailgun sends individual emails to each recipient in the to field. Without it, each recipient will see all recipients&rsquo; email addresses in the to field.<\/p>\n\n<p class=\"wp-block-paragraph\">Here is one such recipient variable, with email addresses as keys and the corresponding \u00ab\u00a0name\u00a0\u00bb and \u00ab\u00a0id\u00a0\u00bb as values:<\/p>\n\n<p class=\"wp-block-paragraph\">{\u00ab\u00a0manish@example.com\u00a0\u00bb: {\u00ab\u00a0name\u00a0\u00bb: \u00ab\u00a0Manish\u00a0\u00bb, \u00ab\u00a0id\u00a0\u00bb: 1},<\/p>\n\n<p class=\"wp-block-paragraph\">\u00ab\u00a0jakkie@example.com\u00a0\u00bb: {\u00ab\u00a0name\u00a0\u00bb: \u00ab\u00a0Jakkie\u00a0\u00bb, \u00ab\u00a0id\u00a0\u00bb: 2},<\/p>\n\n<p class=\"wp-block-paragraph\">\u00ab\u00a0elzet@example.com\u00a0\u00bb: {\u00ab\u00a0name\u00a0\u00bb: \u00ab\u00a0Elzet\u00a0\u00bb, \u00ab\u00a0id\u00a0\u00bb: 3}}<\/p>\n\n<p class=\"wp-block-paragraph\">The send_batch_emails(&#8230;) function has three parameters: recipients, subject, and message. Note that recipients is a dictionary object representing the recipient variable discussed above.<\/p>\n\n<p class=\"wp-block-paragraph\">The code first extracts email addresses from this dictionary using to_address = list(recipients.keys()), then converts the dictionary to JSON for API use with the recipients_json = json.dumps(recipients) call.<\/p>\n\n<p class=\"wp-block-paragraph\">The recipients_json variable is passed in the API call for the recipient-variables field, which is used for personalizing the email subject and content. The subject is specified as follows:<\/p>\n\n<p class=\"wp-block-paragraph\">\u00ab\u00a0Hi, %recipient.name%!\u00a0\u00bb<\/p>\n\n<p class=\"wp-block-paragraph\">The Mailgun API correctly substitutes each recipient&rsquo;s name from the JSON while sending emails with %recipient.name%. So, in the example above, Manish, Jakkie, and Elzet will receive personalized subject lines\u2014\u00a0\u00bbHi, Manish!\u00a0\u00bb \u00ab\u00a0Hi, Jakkie!\u00a0\u00bb, and \u00ab\u00a0Hi, Elzet!\u00a0\u00bb. Similarly, you can personalize the email content using any %recipient.KEY-NAME% value.<\/p>\n\n<p class=\"wp-block-paragraph\">The rest of the send_batch_emails(&#8230;) code is similar to the send_single_email(&#8230;) function, except that it sends multiple email recipients in a single API call.<\/p>\n\n<p class=\"wp-block-paragraph\">Running this script will show the following:<\/p>\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4970\" width=\"800\" height=\"160\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/undefined_-_Imgur__1_.gif\" alt=\"Python script running in terminal\" \/><\/figure>\n    <div data-content-type=\"longform\"  class=\"callout text-body-color px-5 py-6 px-md-6 px-lg-7 py-md-7 longform-spacings rounded-lg bg-light\" data-theme=\"light\">\r\n\r\n        <div class=\"content-body\"> Keep in mind: The maximum number of recipients allowed in a single Mailgun Batch Sending API call is one thousand. You can find more about the <a href='https:\/\/documentation.mailgun.com\/docs\/mailgun\/user-manual\/sending-messages\/#batch-sending'>Batch Sending API here<\/a>.<\/div>\r\n    <\/div>\r\n\n<p class=\"wp-block-paragraph\">Here&rsquo;s an example of how this email will appear in the recipient&rsquo;s inbox:<\/p>\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4971\" width=\"1428\" height=\"344\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image5-2.png\" alt=\"Email sent using Mailgun API\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image5-2.png 1428w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image5-2-300x72.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image5-2-768x185.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/image5-2-1024x247.png 1024w\" sizes=\"(max-width: 1428px) 100vw, 1428px\" \/><\/figure>\n\n<h2 class=\"wp-block-heading\">Additional features of Mailgun&rsquo;s email API<\/h2>\n\n<p class=\"wp-block-paragraph\">The Mailgun API offers several additional features to make your life easier.<\/p>\n\n<h3 class=\"wp-block-heading\">Sending HTML emails with attachments<\/h3>\n\n<p class=\"wp-block-paragraph\">The Mailgun API lets you <a href=\"https:\/\/documentation.mailgun.com\/docs\/mailgun\/user-manual\/sending-messages\/#send-with-attachments\" target=\"_tabs\" rel=\"noopener noreferrer\">send emails with attachments<\/a>, whether with text or HTML content. You can use the same API endpoint (https:\/\/api.mailgun.net\/v3\/YOUR_DOMAIN_NAME\/messages) with an additional &lsquo;attachment&rsquo; passed to the files parameter, as shown below:<\/p>\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                Python                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-Python\">\r\n                                <code id=\"code_0_content\" class=\"language-Python\">\r\n\r\n                                    ```pythonrnfiles = {&#039;attachment&#039;: open(&#039;weekly-report.csv&#039;, &#039;rb&#039;)} \u00a0 \u00a0 # file you want to attachrnresp = requests.post(MAILGUN_API_URL, auth=(&quot;api&quot;, api_key), files=files,rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data={&quot;from&quot;: FROM_EMAIL_ADDRESS,rn\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&quot;to&quot;: to_address, &quot;subject&quot;: subject, &quot;text&quot;: message})rn```\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n<h3 class=\"wp-block-heading\">Email delivery and tracking<\/h3>\n\n<p class=\"wp-block-paragraph\">Mailgun provides <a href=\"https:\/\/documentation.mailgun.com\/docs\/mailgun\/user-manual\/tracking-messages\/\" target=\"_tabs\" rel=\"noopener noreferrer\">detailed email tracking<\/a>, including when emails are delivered or opened, links are clicked, emails bounce, users unsubscribe, and emails are marked as spam. This data is made available via the control panel on the dashboard and through the API.<\/p>\n\n<p class=\"wp-block-paragraph\">Mailgun also permanently saves emails if they can&rsquo;t be delivered (hard bounce) or if a recipient unsubscribes or marks the email as spam. In these cases, Mailgun won&rsquo;t try to send emails to those recipients again.<\/p>\n\n<h3 class=\"wp-block-heading\">Email templates<\/h3>\n\n<p class=\"wp-block-paragraph\">The Mailgun API allows you to <a href=\"https:\/\/documentation.mailgun.com\/docs\/mailgun\/user-manual\/sending-messages\/#templates\" target=\"_tabs\" rel=\"noopener noreferrer\">create HTML templates<\/a> for standardizing your email layout and making them more appealing with predesigned layouts and standard content.<\/p>\n\n<p class=\"wp-block-paragraph\">You can find templates in the left sidebar under the Sending menu.<\/p>\n\n<h3 class=\"wp-block-heading\">Email testing\u00a0<\/h3>\n\n<p class=\"wp-block-paragraph\">Mailgun\u00a0also provides email testing tools to help ensure your messages look and perform as expected. With<a href=\"https:\/\/www.mailgun.com\/fr\/produits\/inspecter\/?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noreferrer noopener\">\u00a0Inspect<\/a>, you can automatically check for issues like broken links, missing images, or spam triggers. The<a href=\"https:\/\/www.mailgun.com\/fr\/fonctionnalites\/previsualisation-email\/?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noreferrer noopener\">\u00a0Email Preview<\/a>\u00a0feature lets you see how your email will\u00a0render\u00a0across different clients and devices, while<a href=\"https:\/\/www.mailgun.com\/fr\/fonctionnalites\/accessibilite-emails\/?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noreferrer noopener\">\u00a0Email Accessibility<\/a>\u00a0testing helps confirm your content is compliant with accessibility standards. You can learn more about Mailgun\u2019s <a href=\"https:\/\/www.mailgun.com\/fr\/solutions\/logiciel-test-email\/?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noreferrer noopener\">email testing software<\/a>\u00a0and integrate these checks into your workflow when building emails with the API.\u00a0<\/p>\n\n<h2 class=\"wp-block-heading\">Alternative Python email libraries\u00a0<\/h2>\n\n<p class=\"wp-block-paragraph\">Before reaching for a dedicated email API,\u00a0it\u2019s\u00a0worth understanding the native tools Python provides for sending email, along with a few lightweight third-party options.\u00a0<\/p>\n\n<p class=\"wp-block-paragraph\">Python includes two core modules for SMTP-based email:\u00a0smtplib\u00a0and email.\u00a0\u00a0<\/p>\n\n<h3 class=\"wp-block-heading\">smtplib\u00a0<\/h3>\n\n<p class=\"wp-block-paragraph\">The\u00a0smtplib\u00a0module manages SMTP sessions, allowing you to connect to an SMTP server using SMTP_SSL() for implicit TLS (typically port 465) or\u00a0SMTP() with\u00a0starttls() for opportunistic TLS (commonly port 587). Authentication is handled with a standard username and password.\u00a0<\/p>\n\n<p class=\"wp-block-paragraph\">The email package\u00a0is responsible for\u00a0message construction.\u00a0EmailMessage\u00a0offers a modern, high-level API, while\u00a0MIMEText\u00a0and\u00a0MIMEMultipart\u00a0support plain text, HTML, and multipart payloads.\u00a0<\/p>\n\n<p class=\"wp-block-paragraph\">This code builds a simple email and sends it securely through an SMTP server using Python:<\/p>\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                Python                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-Python\">\r\n                                <code id=\"code_0_content\" class=\"language-Python\">\r\n\r\n                                    from\u00a0email.message\u00a0import EmailMessage\u00a0\r\nimport smtplib\u00a0\r\n\u00a0\r\nmsg =\u00a0EmailMessage()\u00a0\r\nmsg[&quot;From&quot;] = &quot;you@example.com&quot;\u00a0\r\nmsg[&quot;To&quot;] = &quot;friend@example.com&quot;\u00a0\r\nmsg[&quot;Subject&quot;] = &quot;Hello&quot;\u00a0\r\nmsg.set_content(&quot;Sent with Python!&quot;)\u00a0\r\n\u00a0\r\nwith\u00a0smtplib.SMTP(&quot;smtp.example.com&quot;, 587) as smtp:\u00a0\r\n\u00a0\u00a0\u00a0\u00a0smtp.starttls()\u00a0\r\n\u00a0\u00a0\u00a0\u00a0smtp.login(&quot;username&quot;, &quot;password&quot;)\u00a0\r\n\u00a0\u00a0\u00a0\u00a0smtp.send_message(msg)\u00a0\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n<h3 class=\"wp-block-heading\">Yagmail\u00a0<\/h3>\n\n<p class=\"wp-block-paragraph\">Several third-party libraries further reduce boilerplate.\u00a0Yagmail\u00a0provides a Gmail-focused abstraction for sending messages and attachments with minimal configuration.\u00a0python-emails\u00a0adds\u00a0higher-level features such as template rendering, structured message composition, and DKIM signing.\u00a0<\/p>\n\n<p class=\"wp-block-paragraph\">As a general rule, avoid hard-coding credentials.\u00a0Use Python\u2019s\u00a0getpass() for secure password input, store API keys in environment variables, and always\u00a0transmit\u00a0email over TLS-encrypted connections.\u00a0<\/p>\n\n<h2 class=\"wp-block-heading\">Authentication and security\u00a0<\/h2>\n\n<p class=\"wp-block-paragraph\">It\u2019s\u00a0important to keep\u00a0some\u00a0best practices\u00a0and tips\u00a0in mind when you send emails programmatically.\u00a0<\/p>\n\n<h3 class=\"wp-block-heading\">Error handling\u00a0<\/h3>\n\n<p class=\"wp-block-paragraph\">When your script uses a third-party API like\u00a0Mailgun\u00a0to send emails, you must handle potential errors related to network or API failures and API responses indicating errors to ensure your script works smoothly, can detect issues like invalid API keys or URLs, and knows when emails aren\u2019t sent by the\u00a0Mailgun\u00a0API. Without error handling, your script might fail silently, resulting in undelivered emails.\u00a0<\/p>\n\n<p class=\"wp-block-paragraph\">The code snippets\u00a0above all provide\u00a0for handling errors that might occur. Firstly, they check the response status code (resp.status_code). If\u00a0it\u2019s\u00a0not successful (HTTP 200), they\u00a0log\u00a0the error message so you can debug the issue.\u00a0<\/p>\n\n<p class=\"wp-block-paragraph\">Both the\u00a0send_single_email(\u2026) and\u00a0send_batch_emails(\u2026) functions also use a try-except block to ensure any exceptions are caught and logged correctly.\u00a0<\/p>\n\n<h3 class=\"wp-block-heading\">Email deliverability\u00a0<\/h3>\n\n<p class=\"wp-block-paragraph\">Email deliverability means ensuring your emails land in the recipient\u2019s inbox, not their spam folder. You need a good sender reputation to achieve high deliverability. When\u00a0we\u2019re\u00a0talking about building programmatic sending, there are a couple specific things we can look at to improve your email deliverability including\u00a0authentication, and\u00a0optimizing\u00a0emails to be responsive.\u00a0\u00a0<\/p>\n\n<h3 class=\"wp-block-heading\">Authenticate your email\u00a0<\/h3>\n\n<p class=\"wp-block-paragraph\">Use SPF, DKIM, and DMARC to\u00a0validate\u00a0your identity as a sender. Only send emails to verified subscribers who have opted in to receive them and regularly remove inactive subscribers and those who mark your emails as spam.\u00a0<\/p>\n    <div data-content-type=\"longform\"  class=\"callout text-body-color px-5 py-6 px-md-6 px-lg-7 py-md-7 longform-spacings rounded-lg bg-light\" data-theme=\"light\">\r\n\r\n        <div class=\"content-body\"> <p class=\"mb-0\">DMARC is becoming an industry&nbsp;requirement. Learn more about why, and what this authentication standard does in our post on the <a href=\"https:\/\/www.mailgun.com\/fr\/blog\/deliverability\/dmarc-conseils-de-dmarcian\/\">DMARC perspective<\/a>.<\/p><\/div>\r\n    <\/div>\r\n\n<h2 class=\"wp-block-heading\">Start sending with Python3 and\u00a0Mailgun&rsquo;s\u00a0Email API<\/h2>\n\n<p class=\"wp-block-paragraph\">In this article, you learned how to send emails using a Python script and the Mailgun API. You also learned about Mailgun features like email tracking and templates and the importance of error handling, optimizing deliverability, and sending responsive emails.<\/p>\n\n<p class=\"wp-block-paragraph\">Email geeks help other email geeks. You can find the code discussed in this tutorial in <a href=\"https:\/\/github.com\/manishh\/gifts-giveaways\/tree\/master\/python\/mailgun-api-demo\" target=\"_tabs\" rel=\"noopener noreferrer\">this GitHub repo<\/a>.<\/p>\n\n<p class=\"wp-block-paragraph\">Was this helpful? If so, be sure to subscribe to our newsletter for more tutorials, announcements, and industry insights.<\/p>\n\n<h2 class=\"wp-block-heading\">FAQs<\/h2>\n    <div data-content-type=\"longform\" id=\"accordion-id-block_62ff46c3f3bc674de9eddf72b3862416\" class=\"accordion accordion-longform d-flex flex-column gap-3 my-3\">\r\n\r\n        \n\r\n\r\n<div class=\"accordion-item py-2 border-bottom\">\r\n    <div\r\n        id=\"title-block_2848aeb1ce02e8475435f7726c35ef66_9314\"\r\n        class=\"accordion-header pb-3\">\r\n\r\n        <button\r\n            class=\"accordion-button fs-5 collapsed\"\r\n            type=\"button\"\r\n            data-bs-toggle=\"collapse\"\r\n            data-bs-target=\"#accordion-collapse-block_2848aeb1ce02e8475435f7726c35ef66_9314\"\r\n            aria-expanded=\"false\"\r\n            aria-controls=\"accordion-collapse-block_2848aeb1ce02e8475435f7726c35ef66_9314\">\r\n            How do I send emails using Python\u2019s smtplib module with TLS and SSL?         <\/button>\r\n    <\/div>\r\n    <div\r\n        id=\"accordion-collapse-block_2848aeb1ce02e8475435f7726c35ef66_9314\"\r\n        class=\"accordion-collapse collapse\"\r\n        aria-labelledby=\"title-block_2848aeb1ce02e8475435f7726c35ef66_9314\">\r\n        <div class=\"accordion-body pb-3\">\r\n            \n\n<p class=\"wp-block-paragraph\">Use TLS (STARTTLS) on port 587 when you want to upgrade a plain connection to encrypted, and SSL (implicit TLS) on port 465 when the connection starts encrypted.\u00a0<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>TLS (STARTTLS):\u00a0<\/strong>smtplib.SMTP(host, 587) \u2192\u00a0starttls() \u2192\u00a0login() \u2192\u00a0send_message()\u00a0<\/li>\n\n\n\n<li><strong>SSL (implicit TLS):\u00a0<\/strong>smtplib.SMTP_SSL(host, 465) \u2192\u00a0login() \u2192\u00a0send_message()\u00a0<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In both cases, construct the message (for example with\u00a0EmailMessage) and send it with\u00a0smtp.send_message(msg). Always authenticate using SMTP credentials (username\/password) provided by your provider.\u00a0<\/p>\n\n\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\n\n\r\n\r\n<div class=\"accordion-item py-2 border-bottom\">\r\n    <div\r\n        id=\"title-block_9d98f1f857e0657526c304053e1358a2_9122\"\r\n        class=\"accordion-header pb-3\">\r\n\r\n        <button\r\n            class=\"accordion-button fs-5 collapsed\"\r\n            type=\"button\"\r\n            data-bs-toggle=\"collapse\"\r\n            data-bs-target=\"#accordion-collapse-block_9d98f1f857e0657526c304053e1358a2_9122\"\r\n            aria-expanded=\"false\"\r\n            aria-controls=\"accordion-collapse-block_9d98f1f857e0657526c304053e1358a2_9122\">\r\n            What are the differences between EmailMessage, MIMEText, and MIMEMultipart when constructing messages?        <\/button>\r\n    <\/div>\r\n    <div\r\n        id=\"accordion-collapse-block_9d98f1f857e0657526c304053e1358a2_9122\"\r\n        class=\"accordion-collapse collapse\"\r\n        aria-labelledby=\"title-block_9d98f1f857e0657526c304053e1358a2_9122\">\r\n        <div class=\"accordion-body pb-3\">\r\n            \n\n<ul class=\"wp-block-list\">\n<li><strong>EmailMessage:<\/strong> Modern, high-level API. Best default choice for most use cases. Makes it easy to set headers, add plain text, add HTML alternatives (add_alternative()), and attach files with less boilerplate.\u00a0<\/li>\n\n\n\n<li><strong>MIMEText:<\/strong> Lower-level building block for a single text part (plain text or HTML). Useful when you want explicit control over a single body part.\u00a0<\/li>\n\n\n\n<li><strong>MIMEMultipart: <\/strong>Container for combining multiple MIME parts (text + HTML + attachments). Common in older\u00a0examples;\u00a0you manually attach\u00a0MIMEText\u00a0parts and files.\u00a0<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If\u00a0you\u2019re\u00a0starting fresh, prefer\u00a0EmailMessage\u00a0unless you need compatibility with older MIME-building patterns.\u00a0<\/p>\n\n\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\n\n\r\n\r\n<div class=\"accordion-item py-2 border-bottom\">\r\n    <div\r\n        id=\"title-block_6d54bff47f76bba6d0dcc13fd9c3fcfc_7368\"\r\n        class=\"accordion-header pb-3\">\r\n\r\n        <button\r\n            class=\"accordion-button fs-5 collapsed\"\r\n            type=\"button\"\r\n            data-bs-toggle=\"collapse\"\r\n            data-bs-target=\"#accordion-collapse-block_6d54bff47f76bba6d0dcc13fd9c3fcfc_7368\"\r\n            aria-expanded=\"false\"\r\n            aria-controls=\"accordion-collapse-block_6d54bff47f76bba6d0dcc13fd9c3fcfc_7368\">\r\n            How can I use environment variables and the getpass() module for secure credential management?         <\/button>\r\n    <\/div>\r\n    <div\r\n        id=\"accordion-collapse-block_6d54bff47f76bba6d0dcc13fd9c3fcfc_7368\"\r\n        class=\"accordion-collapse collapse\"\r\n        aria-labelledby=\"title-block_6d54bff47f76bba6d0dcc13fd9c3fcfc_7368\">\r\n        <div class=\"accordion-body pb-3\">\r\n            \n\n<p class=\"wp-block-paragraph\">Use environment variables for credentials in deployed apps (CI\/CD, containers, servers), and\u00a0getpass() for interactive local scripts.\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Environment\u00a0variables keep secrets out of source control and logs. Store values like SMTP usernames\/passwords or API\u00a0keys\u00a0as SMTP_USER, SMTP_PASS, MAILGUN_API_KEY, etc., and read them at runtime.\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">getpass.getpass() securely prompts for a password without echoing it to the terminal\u2014useful for quick scripts or local testing.\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A common pattern\u00a0is:\u00a0read from env\u00a0first, and\u00a0fall back to\u00a0getpass() only if missing.\u00a0<\/p>\n\n\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\n\n\r\n\r\n<div class=\"accordion-item py-2 border-bottom\">\r\n    <div\r\n        id=\"title-block_5cce729ff4b03511d1064c4c364e3eea_3429\"\r\n        class=\"accordion-header pb-3\">\r\n\r\n        <button\r\n            class=\"accordion-button fs-5 collapsed\"\r\n            type=\"button\"\r\n            data-bs-toggle=\"collapse\"\r\n            data-bs-target=\"#accordion-collapse-block_5cce729ff4b03511d1064c4c364e3eea_3429\"\r\n            aria-expanded=\"false\"\r\n            aria-controls=\"accordion-collapse-block_5cce729ff4b03511d1064c4c364e3eea_3429\">\r\n            What advantages does Yagmail provide over smtplib for Gmail users?         <\/button>\r\n    <\/div>\r\n    <div\r\n        id=\"accordion-collapse-block_5cce729ff4b03511d1064c4c364e3eea_3429\"\r\n        class=\"accordion-collapse collapse\"\r\n        aria-labelledby=\"title-block_5cce729ff4b03511d1064c4c364e3eea_3429\">\r\n        <div class=\"accordion-body pb-3\">\r\n            \n\n<p class=\"wp-block-paragraph\">Yagmail\u00a0is designed specifically for Gmail workflows, so it reduces SMTP boilerplate and smooths out common Gmail tasks.\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Key advantages for Gmail users:\u00a0<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Less code:<\/strong> minimal setup to send messages, HTML, and attachments.\u00a0<\/li>\n\n\n\n<li><strong>Gmail-oriented ergonomics: <\/strong>friendlier API for composing messages and handling attachments.\u00a0<\/li>\n\n\n\n<li><strong>Faster iteration: <\/strong>good for scripts and internal tools where you want \u201csend email\u201d to be simple without manually managing MIME parts.\u00a0<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If\u00a0you\u2019re\u00a0strictly sending through Gmail and want fewer moving pieces than raw\u00a0smtplib\u00a0+ MIME construction,\u00a0Yagmail\u00a0is often the quickest path.\u00a0<\/p>\n\n\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\n\n\r\n\r\n<div class=\"accordion-item py-2 border-bottom\">\r\n    <div\r\n        id=\"title-block_48a68aa684b650e88fa00e2f1236ea45_5065\"\r\n        class=\"accordion-header pb-3\">\r\n\r\n        <button\r\n            class=\"accordion-button fs-5 collapsed\"\r\n            type=\"button\"\r\n            data-bs-toggle=\"collapse\"\r\n            data-bs-target=\"#accordion-collapse-block_48a68aa684b650e88fa00e2f1236ea45_5065\"\r\n            aria-expanded=\"false\"\r\n            aria-controls=\"accordion-collapse-block_48a68aa684b650e88fa00e2f1236ea45_5065\">\r\n            How do I implement DKIM signing and template rendering with the python-emails library?         <\/button>\r\n    <\/div>\r\n    <div\r\n        id=\"accordion-collapse-block_48a68aa684b650e88fa00e2f1236ea45_5065\"\r\n        class=\"accordion-collapse collapse\"\r\n        aria-labelledby=\"title-block_48a68aa684b650e88fa00e2f1236ea45_5065\">\r\n        <div class=\"accordion-body pb-3\">\r\n            \n\n<p class=\"wp-block-paragraph\">With python-emails,\u00a0you\u00a0typically:\u00a0<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Render a template (often HTML + text) using the\u00a0library\u2019s\u00a0templating\u00a0helpers (or pass pre-rendered content from your own template engine).\u00a0<\/li>\n\n\n\n<li>Attach DKIM settings using your\u00a0domain\u2019s\u00a0DKIM private key and selector before sending.\u00a0<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In practice,\u00a0you\u2019ll:\u00a0<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Build an email object (subject\/from\/to)\u00a0<\/li>\n\n\n\n<li>Provide rendered HTML\/text bodies (and optionally variables for templates)\u00a0<\/li>\n\n\n\n<li>Configure DKIM signing using:&nbsp;\n<ul class=\"wp-block-list\">\n<li>a selector (e.g.,\u00a0mailgun\u00a0or default)\u00a0<\/li>\n\n\n\n<li>your signing domain\u00a0<\/li>\n\n\n\n<li>the DKIM private key (loaded securely from environment variables or a secrets manager)\u00a0<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">For production, keep the DKIM private key out of source code (environment variables or mounted secret files), and\u00a0validate\u00a0signing by checking message headers in a mailbox that shows DKIM-Signature and authentication results.\u00a0<\/p>\n\n\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\n\r\n\r\n\r\n\r\n\r\n    <\/div>\r\n\r\n    \r\n    <div data-content-type=\"longform\" class=\"longform-spacings\">\r\n        <div class=\"cta bg-primary rounded-lg px-5 py-6 p-md-7 px-md-6\">\r\n                    <div class=\"form-subscription\">\r\n                            <div class=\"h4 mb-3\">\r\n                    Keep me posted! Get great resources in your inbox every week.                <\/div>\r\n                                    <form accept-charset=\"UTF-8\" action=\"\" enctype=\"multipart\/form-data\" data-form-subscription method=\"POST\" style=\"max-width: 400px;\">\r\n                <div class=\"row justify-content-between align-items-top g-2\">\r\n                    <div class=\"col-10\">\r\n                        <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"Email\" autocomplete=\"email\" required>\r\n                        <div data-fs=\"error\" role=\"alert\" class=\"invalid-feedback\">\r\n                            Please complete this required field.                        <\/div>\r\n                    <\/div>\r\n                                            <div class=\"col-12 order-last mt-3 fs-xxs\" data-fs=\"acceptance\" style=\"display:none;\">\r\n                            \r\n                                <div class=\"form-check\">\r\n                                    <input id=\"formSubscriptionAcceptance-terms-5854\" class=\"form-check-input\"\r\n                                        type=\"checkbox\" name=\"terms\">\r\n                                    <label for=\"formSubscriptionAcceptance-terms-5854\" class=\"form-check-label text-body-color\">\r\n                                        J&rsquo;ai lu et j&rsquo;accepte les conditions d&rsquo;utilisation.                                        <span class=\"hs-form-required\">*<\/span>\r\n                                    <\/label>\r\n                                <\/div>\r\n\r\n                            \r\n                                <div class=\"form-check\">\r\n                                    <input id=\"formSubscriptionAcceptance-privacy-6218\" class=\"form-check-input\"\r\n                                        type=\"checkbox\" name=\"privacy\">\r\n                                    <label for=\"formSubscriptionAcceptance-privacy-6218\" class=\"form-check-label text-body-color\">\r\n                                        J&rsquo;ai lu et j&rsquo;accepte la politique de confidentialit\u00e9.                                        <span class=\"hs-form-required\">*<\/span>\r\n                                    <\/label>\r\n                                <\/div>\r\n\r\n                                                    <\/div>\r\n                    \r\n                                            <div class=\"col-12 order-last fs-xxs mb-0 mt-2 text-body-color\">\r\n                            Send me the Mailjet Newsletter. I expressly agree to receive the newsletter and know that I can easily unsubscribe at any time.                        <\/div>\r\n                    \r\n                    <div class=\"col-2\">\r\n                        <button type=\"submit\" value=\"Submit\" aria-label=\"Submit\" class=\"btn btn-secondary btn-icon\">\r\n                            <svg aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/layout\/chevron-right.svg\"><\/svg>\r\n                        <\/button>\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <input type=\"hidden\" name=\"formSubscriptionRecaptchaToken\" data-fs=\"recaptcha-token\">\r\n                <input type=\"hidden\" name=\"customListID\" value=\"\">\r\n\r\n            <\/form>\r\n            <div data-fs=\"message-success\" style=\"display: none;\">\r\n                <p class=\"mb-0 mt-2 text-body-color\">\r\n                    Check your inbox monthly for your Mailjet Newsletter!                <\/p>\r\n            <\/div>\r\n        <\/div>\r\n        <\/div>\r\n    <\/div>\r\n","protected":false},"excerpt":{"rendered":"<p>Vous cherchez \u00e0 simplifier votre processus d&rsquo;envoi d&#8217;emails avec Python3\u00a0? Nous avons r\u00e9uni nos sp\u00e9cialistes Python pour vous proposer ce guide. Dans ce tutoriel, nous allons analyser la m\u00e9thode pour envoyer des emails de mani\u00e8re programmatique avec Python3 et l&#8217;email API de Sinch Mailgun.<\/p>\n","protected":false},"author":11,"featured_media":4843,"menu_order":0,"template":"","meta":{"_acf_changed":false,"footnotes":""},"blog_category":[23],"class_list":["post-24699","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog_category-it-and-engineering"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Guide de l&#039;API d&#039;email Python : envoyer des emails avec Mailgun - Transactional Email API Service For Developers | Mailgun<\/title>\n<meta name=\"description\" content=\"D\u00e9couvrez comment int\u00e9grer l&#039;envoi d&#039;emails programmatique avec notre tutoriel \u00e9tape par \u00e9tape utilisant Python et l&#039;API d&#039;email de Mailgun. Commencez \u00e0 envoyer des emails sans effort d\u00e8s aujourd&#039;hui !\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Guide de l&#039;API d&#039;email Python : envoyer des emails avec Mailgun - Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"og:description\" content=\"D\u00e9couvrez comment int\u00e9grer l&#039;envoi d&#039;emails programmatique avec notre tutoriel \u00e9tape par \u00e9tape utilisant Python et l&#039;API d&#039;email de Mailgun. Commencez \u00e0 envoyer des emails sans effort d\u00e8s aujourd&#039;hui !\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-16T19:09:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png\" \/>\n\t<meta property=\"og:image:width\" content=\"720\" \/>\n\t<meta property=\"og:image:height\" content=\"448\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/envoyer-email-avec-python\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/envoyer-email-avec-python\\\/\",\"name\":\"Guide de l'API d'email Python : envoyer des emails avec Mailgun - Transactional Email API Service For Developers | Mailgun\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/envoyer-email-avec-python\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/envoyer-email-avec-python\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"datePublished\":\"2026-01-15T13:06:37+00:00\",\"dateModified\":\"2026-09-16T19:09:16+00:00\",\"description\":\"D\u00e9couvrez comment int\u00e9grer l'envoi d'emails programmatique avec notre tutoriel \u00e9tape par \u00e9tape utilisant Python et l'API d'email de Mailgun. Commencez \u00e0 envoyer des emails sans effort d\u00e8s aujourd'hui !\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/envoyer-email-avec-python\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/envoyer-email-avec-python\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/envoyer-email-avec-python\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"width\":720,\"height\":448},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/envoyer-email-avec-python\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Envoyer des emails avec Python3 et l\u2019API de Mailgun\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#website\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"description\":\"Des API d\u2019emails transactionnels puissantes qui vous permettent d'envoyer, de recevoir et de suivre des emails, con\u00e7ues pour les d\u00e9veloppeurs. En savoir plus d\u00e8s aujourd'hui !\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#organization\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"width\":512,\"height\":512,\"caption\":\"Transactional Email API Service For Developers | Mailgun\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Guide de l'API d'email Python : envoyer des emails avec Mailgun - Transactional Email API Service For Developers | Mailgun","description":"D\u00e9couvrez comment int\u00e9grer l'envoi d'emails programmatique avec notre tutoriel \u00e9tape par \u00e9tape utilisant Python et l'API d'email de Mailgun. Commencez \u00e0 envoyer des emails sans effort d\u00e8s aujourd'hui !","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/","og_locale":"fr_FR","og_type":"article","og_title":"Guide de l'API d'email Python : envoyer des emails avec Mailgun - Transactional Email API Service For Developers | Mailgun","og_description":"D\u00e9couvrez comment int\u00e9grer l'envoi d'emails programmatique avec notre tutoriel \u00e9tape par \u00e9tape utilisant Python et l'API d'email de Mailgun. Commencez \u00e0 envoyer des emails sans effort d\u00e8s aujourd'hui !","og_url":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/","og_site_name":"Transactional Email API Service For Developers | Mailgun","article_modified_time":"2026-09-16T19:09:16+00:00","og_image":[{"width":720,"height":448,"url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/","url":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/","name":"Guide de l'API d'email Python : envoyer des emails avec Mailgun - Transactional Email API Service For Developers | Mailgun","isPartOf":{"@id":"https:\/\/www.mailgun.com\/fr\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/#primaryimage"},"image":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","datePublished":"2026-01-15T13:06:37+00:00","dateModified":"2026-09-16T19:09:16+00:00","description":"D\u00e9couvrez comment int\u00e9grer l'envoi d'emails programmatique avec notre tutoriel \u00e9tape par \u00e9tape utilisant Python et l'API d'email de Mailgun. Commencez \u00e0 envoyer des emails sans effort d\u00e8s aujourd'hui !","breadcrumb":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/#primaryimage","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","width":720,"height":448},{"@type":"BreadcrumbList","@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/envoyer-email-avec-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.mailgun.com\/fr\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/www.mailgun.com\/fr\/blog\/"},{"@type":"ListItem","position":3,"name":"Envoyer des emails avec Python3 et l\u2019API de Mailgun"}]},{"@type":"WebSite","@id":"https:\/\/www.mailgun.com\/fr\/#website","url":"https:\/\/www.mailgun.com\/fr\/","name":"Transactional Email API Service For Developers | Mailgun","description":"Des API d\u2019emails transactionnels puissantes qui vous permettent d'envoyer, de recevoir et de suivre des emails, con\u00e7ues pour les d\u00e9veloppeurs. En savoir plus d\u00e8s aujourd'hui !","publisher":{"@id":"https:\/\/www.mailgun.com\/fr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.mailgun.com\/fr\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/www.mailgun.com\/fr\/#organization","name":"Transactional Email API Service For Developers | Mailgun","url":"https:\/\/www.mailgun.com\/fr\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.mailgun.com\/fr\/#\/schema\/logo\/image\/","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","width":512,"height":512,"caption":"Transactional Email API Service For Developers | Mailgun"},"image":{"@id":"https:\/\/www.mailgun.com\/fr\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog\/24699","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/users\/11"}],"version-history":[{"count":3,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog\/24699\/revisions"}],"predecessor-version":[{"id":24782,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog\/24699\/revisions\/24782"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/media\/4843"}],"wp:attachment":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/media?parent=24699"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog_category?post=24699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}