{"id":13386,"date":"2025-10-28T09:00:00","date_gmt":"2025-10-28T09:00:00","guid":{"rendered":"https:\/\/www.mailgun.com\/blog\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/"},"modified":"2026-04-30T04:28:10","modified_gmt":"2026-04-30T04:28:10","slug":"creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes","status":"publish","type":"blog","link":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/","title":{"rendered":"Cr\u00e9er des sc\u00e9narios d&#8217;emails transactionnels pour les notifications de paniers abandonn\u00e9s avec l&rsquo;API de Mailgun"},"content":{"rendered":"\n<p>In modern ecommerce applications, transactional emails go beyond order confirmations and shipping updates. They also respond to user behavior; for example, if a user adds items to their cart but doesn&rsquo;t complete the purchase, you can send a reminder, commonly known as an \u00ab\u00a0abandoned cart\u00a0\u00bb notification. This not only encourages completion but also provides a helpful touchpoint in case the user encounters any issues during checkout.<\/p>\n\n<p><br \/>In this tutorial, you&rsquo;ll learn how to send an abandoned cart email to users using Mailgun APIs.<\/p>\n\n<h2 class=\"wp-block-heading\">Implementing transactional email workflows for abandoned cart notifications<\/h2>\n\n<p>To implement transactional email workflows for abandoned cart notifications, you&rsquo;ll build a simple UI to simulate a shopping cart and a\u00a0<a href=\"https:\/\/flask.palletsprojects.com\/en\/stable\/\">Flask<\/a>\u00a0backend to track abandoned carts and trigger transactional emails.<\/p>\n\n<p><br \/><strong>Before you begin, make sure you have the following:<\/strong><\/p>\n\n<ul class=\"wp-block-list\">\n<li>A\u00a0<a href=\"https:\/\/signup.mailgun.com\/new\/signup\">Mailgun account<\/a>\u00a0to send emails via Mailgun&rsquo;s API; if you don&rsquo;t have an account, follow the\u00a0<a href=\"https:\/\/documentation.mailgun.com\/docs\/mailgun\/quickstart-guide\/quickstart\/\">quick start guide<\/a>\u00a0to set one up for free<\/li>\n\n\n\n<li><a href=\"https:\/\/www.python.org\/downloads\/\">Python<\/a>\u00a03.8 or higher installed on your machine<\/li>\n\n\n\n<li>Some familiarity with HTML and JavaScript to understand the UI code<\/li>\n<\/ul>\n\n<h2 class=\"wp-block-heading\">Setting up a Mailgun account<\/h2>\n\n<p>First, sign in to your Mailgun account and note your sending domain in the Mailgun dashboard. If you&rsquo;re on a free plan, you&rsquo;ll see a sandbox domain, which will be used in both the API endpoint and th<code>\"from\"<\/code>\u00a0email address when sending emails. The sandbox domain follows this format:\u00a0<code>sandbox&lt;alphanumeric-id&gt;.mailgun.org<\/code>:<br \/><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/7IYAFRf.png\" alt=\"Mailgun sending domain\" \/><br \/><\/p>\n\n<p><strong>Note:<\/strong>\u00a0If you want to send emails from your own custom domain, you&rsquo;ll need a paid Mailgun plan. The free plan only supports the sandbox domain and limits sending to\u00a0<a href=\"https:\/\/help.mailgun.com\/hc\/en-us\/articles\/217531258-Authorized-Recipients\">five authorized recipients<\/a>.<\/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\">If you want to send emails from your own custom domain, you&rsquo;ll need a paid Mailgun plan. The free plan only supports the sandbox domain and limits sending to<a href=\"https:\/\/help.mailgun.com\/hc\/en-us\/articles\/217531258-Authorized-Recipients\">&nbsp;five authorized recipients.<\/a><\/p><\/div>\r\n    <\/div>\r\n\n<p>Next, you need to generate an API key from the\u00a0<strong>API Security<\/strong>\u00a0page. You can find this option in the drop-down menu under your name in the top-right corner of the Mailgun dashboard:<br \/><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/YEm9s1u.png\" alt=\"Creating an API key\" \/><br \/><\/p>\n\n<p>You&rsquo;ll use this API key in your Flask application to send abandoned cart notifications via the Mailgun API.<br \/><\/p>\n\n<h2 class=\"wp-block-heading\">Setting up a new Python project<\/h2>\n\n<p>To set up a new project, open a terminal inside your preferred project directory and run the following commands to fetch the required code \u2013 both the UI and backend \u2013 onto your machine:<\/p>\n\n<p><br \/><code>git clone https:\/\/github.com\/manishh\/gifts-giveaways.git cd gifts-giveaways\/python\/mailgun-abandoned-cart-notifications<\/code><br \/><\/p>\n\n<p>Next, inside the\u00a0<code>mailgun-abandoned-cart-notifications<\/code>\u00a0directory, rename\u00a0<code>.env.example<\/code>\u00a0to\u00a0<code>.env<\/code>, and update it with your Mailgun API credentials:<br \/><code># Replace with your actual Mailgun API key and domain MAILGUN_API_KEY=\"YOUR-API-KEY\" MAILGUN_DOMAIN=\"YOUR-MAILGUN-DOMAIN\"<\/code><br \/><\/p>\n\n<p>Before you proceed, it&rsquo;s recommended that you create and activate a new\u00a0<a href=\"https:\/\/docs.python.org\/3\/library\/venv.html\">virtual environment<\/a>\u00a0to isolate your project and avoid dependency conflicts.<br \/>Once your virtual environment is active, install the required dependencies:<br \/><code>pip install -r requirements.txt<\/code><br \/>This installs all necessary packages, including\u00a0<code>Flask<\/code>, the lightweight web framework that runs the backend.<br \/>After installation is complete, launch the Flask application with this command:<br \/><code>python app.py<\/code><br \/>The application UI will then be available at\u00a0<a href=\"http:\/\/localhost:5000\/\">http:\/\/localhost:5000\/<\/a>.<\/p>\n\n<h2 class=\"wp-block-heading\">Building the abandoned cart interface<\/h2>\n\n<p>The screenshot below shows a simple ecommerce UI for simulating abandoned cart scenarios. At the top, the header displays the title, along with a user profile (showing the name and email) and a shopping cart icon indicating the number of items in the cart. There are four product cards showcasing images, names, prices, and descriptions, and users can select quantities before adding items with the\u00a0<strong>Add to Cart<\/strong>\u00a0button. At the bottom left, a settings panel lets you configure the abandoned cart timeout (in seconds) and reset the cart if needed. In real life, timeout would be in hours, and it should be tracked by the backend.<br \/>You can use this interface to trigger an event when a user leaves items in their cart without completing the purchase:<br \/><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/c99b7OU.png\" alt=\"Abandoned cart UI\" \/><br \/><\/p>\n\n<p>You can find the code for this shopping cart interface in\u00a0<a href=\"https:\/\/github.com\/manishh\/gifts-giveaways\/blob\/master\/python\/mailgun-abandoned-cart-notifications\/templates\/shopping_cart.html\"><code>templates\/shopping_cart.html<\/code><\/a>. This file has two important sections: the UI configuration and a function to send abandoned cart data to the backend.<\/p>\n\n<p><br \/>For the UI configuration, locate and edit\u00a0<code>USER_NAME<\/code>\u00a0and\u00a0<code>USER_EMAIL<\/code>\u00a0within the\u00a0<code>&lt;script&gt;<\/code>\u00a0tag to send the correct data to your backend. These two parameters represent the logged-in user in your ecommerce application:<\/p>\n\n<p><br \/><code>\/\/ Configuration: Replace these with your own values const USER_NAME = \"John Smith\"; const USER_EMAIL = \"john.smith@example.com\"; \/\/ Verified email for Mailgun sandbox account const BACKEND_URL = 'http:\/\/localhost:5000\/abandoned-cart'; \/\/ Update to your Flask API endpoint, if needed let ABANDONED_CART_TIMEOUT = 60; \/\/ Default timeout in seconds<\/code><\/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>Note:&nbsp;If you&rsquo;re using Mailgun&rsquo;s free plan, make sure that&nbsp;USER_EMAIL&nbsp;is one of the verified addresses in your Mailgun account. You can leave the remaining two parameters unchanged.<\/p><\/div>\r\n    <\/div>\r\n\n<p><br \/>The following JavaScript function,\u00a0<code>sendToBackend(data)<\/code>, handles the process of sending abandoned cart details \u2013 such as user information, items in the cart, and the total value \u2013 to the backend for triggering a notification:<\/p>\n\n<p><br \/><code>\/\/ Send data to backend function sendToBackend(data) { console.log('Sending abandoned cart data to backend...'); fetch(BACKEND_URL, { method: 'POST', headers: { 'Content-Type': 'application\/json', }, body: JSON.stringify(data) }) .then(response =&gt; { \/\/ Check if the response status is 200 (OK) if (response.status === 200) { return response.json(); } else { \/\/ Throw an error if the status is not 200 throw new Error(`HTTP error! Status: ${response.status}`); } }) .then(result =&gt; { console.log('Backend response:', result); alert('Abandoned cart notification sent successfully!'); resetCart(); }) .catch(error =&gt; { console.error('Error sending abandoned cart notification:', error); alert('Error sending abandoned cart notification. Check console for details.'); }); }<\/code><\/p>\n\n<p><br \/>This function first makes an HTTP POST request to\u00a0<code>BACKEND_URL<\/code>\u00a0using the\u00a0<code>fetch<\/code>\u00a0call, converting the cart data into a JSON payload.<br \/>If the server responds successfully (HTTP\u00a0<code>200<\/code>), the response is processed and logged to the console, and an alert confirms that the abandoned cart notification was sent. The cart is then reset.<\/p>\n\n<p><br \/>If the request fails \u2013 due to network issues or a server-side problem (such as HTTP\u00a0<code>5XX<\/code>\u00a0errors) \u2013 the function catches the error, logs it to the console, and alerts the user that something went wrong. This way, the function ensures that both successful and failed attempts to notify the backend are handled gracefully, keeping the user informed throughout the process.<\/p>\n\n<p><br \/>The remaining code in\u00a0<code>shopping_cart.html<\/code>\u00a0handles the CSS styling for a clean and visually appealing layout, JavaScript logic for calculating the cart&rsquo;s total value, and timer management to simulate cart abandonment.<\/p>\n\n<h2 class=\"wp-block-heading\">Processing abandoned cart notifications in the backend<\/h2>\n\n<p><br \/>When the UI posts abandoned cart data to\u00a0<code>BACKEND_URL<\/code>, the Flask application (<a href=\"https:\/\/github.com\/manishh\/gifts-giveaways\/blob\/master\/python\/mailgun-abandoned-cart-notifications\/app.py\"><code>app.py<\/code><\/a>) processes it using the following function:<br \/><code>@app.route('\/abandoned-cart', methods=['POST']) def abandoned_cart(): \"\"\" Endpoint to receive abandoned cart data including user information. It sends email notification to the concerned user. \"\"\" try: # Get cart data from request cart_data = request.json # Extract user information user_info = cart_data.get('user', {}) user_email = user_info.get('email', 'unknown') # Log the received data logger.info(f\"Abandoned cart received from {user_email} at {datetime.datetime.now()}, Total items: {len(cart_data.get('items', []))}\") # Send email about the abandoned cart html_message = _generate_abandoned_cart_email(cart_data) _send_email(f\"{user_info.get('name', user_email)} &lt;{user_email}&gt;\", \"Your cart is waiting...\", html_message) # Return success response return jsonify({ \"status\": \"success\", \"message\": f\"Abandoned cart notification sent to: {user_info.get('email')}\", \"timestamp\": datetime.datetime.now().isoformat(), }), 200 except Exception as e: logger.error(f\"Error processing abandoned cart: {str(e)}\") return jsonify({\"status\": \"error\", \"message\": str(e)}), 500<\/code><\/p>\n\n<p><br \/>This API endpoint (<code>\/abandoned-cart<\/code>) listens for POST requests when a user abandons their cart. It extracts the cart details from the request&rsquo;s JSON payload, retrieves the user&rsquo;s email and name, and logs the event along with the timestamp and number of items.<\/p>\n\n<p><br \/>Next, it generates an email using\u00a0<code>_generate_abandoned_cart_email(cart_data)<\/code>, which converts the cart details into a neat HTML email template. The email is then sent to the\u00a0<code>user_email<\/code>\u00a0via\u00a0<code>_send_email()<\/code>, using the subject \u00ab\u00a0Your cart is waiting&#8230;\u00a0\u00bb to remind the user about their pending purchase.<br \/>If successful, the function returns a JSON response confirming that the email was sent. If an error occurs, such as an issue with the request or email service, it logs the error and returns an HTTP\u00a0<code>500 Internal Server Error<\/code>\u00a0response, which the UI can use to inform the user about the notification status.<\/p>\n\n<h2 class=\"wp-block-heading\">Designing the email template<\/h2>\n\n<p>Abandoned cart reminder emails must not only be informative but also visually appealing. A well-designed HTML email with images presents the cart details clearly and increases the chances of the user returning to complete their purchase. The\u00a0<code>_generate_abandoned_cart_email(...)<\/code>\u00a0function takes care of that:<\/p>\n\n<p><br \/><code>def _generate_abandoned_cart_email(cart_data: Dict[str, Any]) -&gt; str: \"\"\" Generate an HTML email for an abandoned cart using the provided cart data. Args: cart_data: Dictionary containing cart information including user details and items Returns: HTML string for the email \"\"\" try: # Extract data with error handling user_name = cart_data.get('user', {}).get('name', 'Valued Customer') first_name = user_name.split()[0] if ' ' in user_name else user_name items = cart_data.get('items', []) total_value = cart_data.get('totalValue', 0) # Format timestamp if available timestamp_str = cart_data.get('timestamp', '') timezone_offset = cart_data.get('timezoneOffset', 0) # Represent the user's time zone if timestamp_str: try: timestamp = datetime.datetime.fromisoformat(timestamp_str.replace('Z', '+00:00')) - datetime.timedelta(minutes=timezone_offset) abandonment_time = f\"on &lt;b&gt;{timestamp.strftime('%B %d at %I:%M %p')}&lt;\/b&gt;\" except (ValueError, TypeError): abandonment_time = 'recently' else: abandonment_time = 'recently' # Generate the HTML content with minimal, combined CSS html = f\"\"\"&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt; &lt;style&gt; \/* CSS styling here *\/ &lt;\/style&gt; &lt;\/head&gt; &lt;body&gt; &lt;div class=\"container\"&gt; &lt;div class=\"header\"&gt; &lt;h1&gt;Your cart is waiting!&lt;\/h1&gt; &lt;\/div&gt; &lt;div class=\"content\"&gt; &lt;p&gt;Hello {first_name},&lt;\/p&gt; &lt;p&gt;We noticed you left some items in your cart {abandonment_time}. Don't worry, we've saved them for you!&lt;\/p&gt; &lt;h2&gt;Your Cart Items:&lt;\/h2&gt;\"\"\" # Add each item to the email for item in items: item_name = item.get('name', 'Product') item_price = item.get('price', 0) item_quantity = item.get('quantity', 1) item_image = item.get('image', '') item_description = item.get('description', '') # Format image tag with fallback image_tag = f'&lt;img src=\"{item_image}\" alt=\"{item_name}\" style=\"max-width:100%; max-height:100%;\"&gt;' if item_image else item_name[0].upper() html += f\"\"\" &lt;div class=\"item\"&gt; &lt;div class=\"img\"&gt;{image_tag}&lt;\/div&gt; &lt;div class=\"details\"&gt; &lt;h3&gt;{item_name}&lt;\/h3&gt; &lt;p style=\"font-size:14px\"&gt;{item_description}&lt;\/p&gt; &lt;p style=\"color:#666\"&gt;Quantity: {item_quantity}&lt;\/p&gt; &lt;p style=\"font-weight:bold\"&gt;${item_price:.2f}&lt;\/p&gt; &lt;\/div&gt; &lt;\/div&gt;\"\"\" # Add total and call to action html += f\"\"\" &lt;div class=\"total\"&gt;Total: ${total_value:.2f}&lt;\/div&gt; &lt;div style=\"text-align:center\"&gt; &lt;a href=\"#\" class=\"btn\"&gt;Complete Your Purchase&lt;\/a&gt; &lt;\/div&gt; &lt;p&gt;If you have any questions about your order, please don't hesitate to contact our customer service team.&lt;\/p&gt; &lt;p&gt;Thank you for shopping with us!&lt;\/p&gt; &lt;\/div&gt; &lt;div class=\"footer\"&gt; &lt;p&gt;\u00a9 2025 Your Company Name. All rights reserved.&lt;\/p&gt; &lt;\/div&gt; &lt;\/div&gt; &lt;\/body&gt; &lt;\/html&gt;\"\"\" return html except Exception as e: # Return a simple fallback email if anything goes wrong return \"\"\"&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;body style=\"font-family:Arial;text-align:center;max-width:600px;margin:auto;padding:20px\"&gt; &lt;h1&gt;Your Cart Is Waiting!&lt;\/h1&gt; &lt;p&gt;Hello there,&lt;\/p&gt; &lt;p&gt;You have items waiting in your cart. Click below to complete your purchase!&lt;\/p&gt; &lt;a href=\"#\" style=\"display:inline-block;background:#eb5454;color:white;padding:10px 20px;text-decoration:none;border-radius:4px;font-weight:bold\"&gt;Complete Your Purchase&lt;\/a&gt; &lt;\/body&gt; &lt;\/html&gt;\"\"\"<\/code><\/p>\n\n<p>This function constructs an HTML email reminding a user about their abandoned cart. It first extracts key details from the provided data, including the user&rsquo;s name, cart items, and total price. If a timestamp is available, it converts it to the user&rsquo;s time zone (since server and client time zones would be different) and formats it into a friendly date-time string (such as \u00ab\u00a0on March 25 at 3:49 PM\u00a0\u00bb). Otherwise, it defaults to \u00ab\u00a0recently.\u00a0\u00bb<\/p>\n\n<p><br \/>The email informs the user that their cart has been saved and lists the items they left behind, including the product name, quantity, price, description, and an image. The total value of the cart is prominently displayed, followed by a\u00a0<strong>Complete Your Purchase<\/strong>\u00a0button to encourage the user to return and finish checkout.<br \/>If an error occurs, such as missing data or formatting issues, the function falls back to a simple email with a basic message and purchase link. This ensures that even if the detailed version fails, users still receive a reminder to complete their transaction.<\/p>\n\n<p><\/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\"> <b>Pro tip:<\/b>&nbsp;Mailgun offers&nbsp;prebuilt email templates&nbsp;and an intuitive visual builder for creating beautiful, responsive emails without writing a single line of code.<\/div>\r\n    <\/div>\r\n\n<p>Navigate to\u00a0<strong>Send &gt; Sending &gt; Templates<\/strong>\u00a0in your Mailgun account to design your own email templates:<br \/><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/rJ9PTpE.png\" alt=\"Email templates\" \/><br \/><\/p>\n\n<h2 class=\"wp-block-heading\">Implementing the email sending functionality with Mailgun&rsquo;s API<\/h2>\n\n<p><br \/>Once the email content is generated, it needs to be delivered reliably. The\u00a0<code>_send_email(...)<\/code>\u00a0function handles sending abandoned cart notifications using Mailgun&rsquo;s API:<\/p>\n\n<p><br \/><code>def _send_email(to_address: str, subject: str, html_message: str): \"\"\" Sends a single email to the given email address using Mailgun API. :param to_address: :param subject: :param message: \"\"\" api_key = os.getenv(\"MAILGUN_API_KEY\") # Get API key from the `.env` file resp = requests.post(MAILGUN_API_URL, auth=(\"api\", api_key), data={\"from\": FROM_EMAIL_ADDRESS, \"to\": to_address, \"subject\": subject, \"html\": html_message}) if resp.status_code == 200: # Success logging.info(f\"Successfully sent an email to '{to_address}' via Mailgun API.\") else: # Error raise RuntimeError(f\"Could not send the email, reason: {resp.text}\")<\/code><\/p>\n\n<p><br \/>This function reads\u00a0<code>MAILGUN_API_KEY<\/code>\u00a0and then sends an email via Mailgun&rsquo;s API using an HTTP POST request. The request includes essential email details, including sender address, recipient address, subject, and HTML content generated by the\u00a0<code>_generate_abandoned_cart_email(...)<\/code>\u00a0function.<br \/>If the request is successful (<code>resp.status_code == 200<\/code>), it logs a success message. Otherwise, it raises an exception with the response details.<br \/>It&rsquo;s important to understand that\u00a0<code>_send_email(...)<\/code>\u00a0deliberately does not handle errors, leaving it to the calling function (<code>abandoned_cart()<\/code>, which serves the\u00a0<code>\/abandoned-cart<\/code>\u00a0endpoint), so that it can catch exceptions and return an appropriate HTTP response. If the email is sent successfully,\u00a0<code>abandoned_cart()<\/code>\u00a0returns an HTTP\u00a0<code>200<\/code>\u00a0response confirming the notification was sent. If an error occurs, such as an invalid API key or network failure, it returns an HTTP\u00a0<code>500<\/code>\u00a0response, ensuring the UI is informed of the issue.<\/p>\n\n<h2 class=\"wp-block-heading\">Testing the workflow<\/h2>\n\n<p>Now that you&rsquo;ve explored all the key components, it&rsquo;s time to test the abandoned cart email workflow end to end.<br \/>First, make sure your Flask server is running and that the UI is accessible in your browser at\u00a0<a href=\"http:\/\/localhost:5000\/\">http:\/\/localhost:5000\/<\/a>. You can adjust the abandoned cart timeout in the settings panel at the bottom left of the page as required.<\/p>\n\n<p><br \/>Next, add a few items to your cart. Each time you add an item, the countdown cart timer resets and starts over. Once you&rsquo;re done, click the cart icon to view the slide-out panel, which displays the selected products, their prices, and the\u00a0<strong>Proceed to Checkout<\/strong>\u00a0button:<\/p>\n\n<p><br \/><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/Qos5lQa.png\" alt=\"Triggering an abandoned cart\" \/><br \/><\/p>\n\n<p>Instead of proceeding with checkout, allow the timer to finish its countdown. Once the countdown reaches zero, an alert should pop up on the UI confirming that the abandoned cart notification was sent. The alert message should read:<br \/><code>Abandoned cart notification sent successfully!<\/code><\/p>\n\n<p><br \/>At the same time, your Flask app&rsquo;s terminal should log messages like this:<br \/><code>INFO:__main__:Abandoned cart received from &lt;redacted-email&gt; at 2025-03-24 14:02:00.077949, Total items: 3 INFO:root:Successfully sent an email to 'Name &lt;redacted-email&gt;' via Mailgun API.<\/code><\/p>\n\n<p><br \/>Finally, check your inbox for the abandoned cart email. If everything worked correctly, you should receive this message:<\/p>\n\n<p><br \/><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/Jd0ferZ.png\" alt=\"Abandoned cart notification email\" \/><\/p>\n\n<p><br \/><strong>Note:<\/strong>\u00a0If you&rsquo;re using Mailgun&rsquo;s free plan, the email may end up in the Spam folder.<\/p>\n\n<p><br \/>Congratulations! You&rsquo;ve successfully implemented and tested the abandoned cart email notification workflow using Mailgun&rsquo;s API.<\/p>\n\n<h2 class=\"wp-block-heading\">Monitoring and managing emails<\/h2>\n\n<p>Once your abandoned cart emails are being sent, it&rsquo;s important to monitor their delivery, track engagement, and handle any failures effectively. Mailgun provides built-in reporting tools to monitor sent emails, open rates, and failures.<\/p>\n\n<p><br \/>To access these insights, navigate to\u00a0<strong>Send &gt; Reporting &gt; Metrics<\/strong>\u00a0in your Mailgun dashboard:<\/p>\n\n<p><br \/><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/J71wf64.png\" alt=\"Mailgun email monitoring\" \/><br \/><\/p>\n\n<p>Here, you&rsquo;ll find a graphical breakdown of key email statistics, such as:<br \/><strong>Sent count:<\/strong>\u00a0Total number of emails attempted<br \/><strong>Delivered count:<\/strong>\u00a0Emails successfully received by recipients<br \/><strong>Opened count:<\/strong>\u00a0Number of emails opened by recipients (if open tracking is enabled)<br \/><strong>Failed count:<\/strong>\u00a0Emails that failed due to issues like invalid addresses or spam filtering<\/p>\n\n<p><br \/>For deeper analysis, the\u00a0<strong>Logs<\/strong>\u00a0tab provides detailed records of each email&rsquo;s status, while the\u00a0<strong>Bounce Classification<\/strong>\u00a0tab helps diagnose failures.<br \/>High bounce rates can negatively impact your email deliverability. To reduce bounces, regularly review the\u00a0<strong>Bounce Classification<\/strong>\u00a0tab in Mailgun, remove invalid emails, and use suppression lists to avoid resending to bounced addresses.<\/p>\n\n<h2 class=\"wp-block-heading\">Wrapping up<\/h2>\n\n<p>In this tutorial, you learned how to implement an abandoned cart email workflow using Mailgun. The process covered building a simple UI to simulate an ecommerce site, sending cart data to the backend, processing it with Flask, generating email templates, sending notifications via the Mailgun API, and tracking delivery metrics. Transactional emails like these help recover lost sales and improve customer engagement.<\/p>\n\n<p><br \/>You can find the entire code for this tutorial in\u00a0<a href=\"https:\/\/github.com\/manishh\/gifts-giveaways\/tree\/master\/python\/mailgun-abandoned-cart-notifications\">this GitHub repository<\/a>.<\/p>\n\n<p><br \/>Now, you can put this knowledge into action \u2013 integrate Mailgun into your projects and start using transactional emails to enhance user experience.\u00a0Explore <a href=\"https:\/\/www.mailgun.com\/fr\/blog\/email\/modeles-d-emails-transactionnels-html\/\">transactional email templates<\/a> and <a href=\"https:\/\/signup.mailgun.com\/new\/signup\">try the Mailgun API<\/a>\u00a0for free today!<\/p>\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-5030\" class=\"form-check-input\"\r\n                                        type=\"checkbox\" name=\"terms\">\r\n                                    <label for=\"formSubscriptionAcceptance-terms-5030\" 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-7467\" class=\"form-check-input\"\r\n                                        type=\"checkbox\" name=\"privacy\">\r\n                                    <label for=\"formSubscriptionAcceptance-privacy-7467\" 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 Mailgun 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\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 Mailgun Newsletter!                <\/p>\r\n            <\/div>\r\n        <\/div>\r\n        <\/div>\r\n    <\/div>\r\n","protected":false},"excerpt":{"rendered":"<p>In modern ecommerce applications, transactional emails go beyond order confirmations and shipping updates. They also respond to user behavior; for example, if a user adds items to their cart but doesn&rsquo;t complete the purchase, you can send a reminder, commonly known as an \u00ab\u00a0abandoned cart\u00a0\u00bb notification. This not only encourages completion but also provides a [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":11750,"menu_order":0,"template":"","meta":{"_acf_changed":true,"footnotes":""},"blog_category":[19],"class_list":["post-13386","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog_category-dev-life"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Build Transactional Email Workflows for Abandoned Cart Messages<\/title>\n<meta name=\"description\" content=\"Learn how to send effective abandoned cart emails using Mailgun APIs to manage and enhance your ecommerce conversions.\" \/>\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\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build Transactional Email Workflows for Abandoned Cart Messages\" \/>\n<meta property=\"og:description\" content=\"Learn how to send effective abandoned cart emails using Mailgun APIs to manage and enhance your ecommerce conversions.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/\" \/>\n<meta property=\"og:site_name\" content=\"Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-30T04:28:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-25-at-3.37.12-PM.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2466\" \/>\n\t<meta property=\"og:image:height\" content=\"1532\" \/>\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=\"10 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\\\/dev-life\\\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/dev-life\\\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\\\/\",\"name\":\"Build Transactional Email Workflows for Abandoned Cart Messages\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/dev-life\\\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/dev-life\\\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/08\\\/Screenshot-2025-08-25-at-3.37.12-PM.png\",\"datePublished\":\"2025-10-28T09:00:00+00:00\",\"dateModified\":\"2026-04-30T04:28:10+00:00\",\"description\":\"Learn how to send effective abandoned cart emails using Mailgun APIs to manage and enhance your ecommerce conversions.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/dev-life\\\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/dev-life\\\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/dev-life\\\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/08\\\/Screenshot-2025-08-25-at-3.37.12-PM.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/08\\\/Screenshot-2025-08-25-at-3.37.12-PM.png\",\"width\":2466,\"height\":1532},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/dev-life\\\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\\\/#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\":\"Cr\u00e9er des sc\u00e9narios d&#8217;emails transactionnels pour les notifications de paniers abandonn\u00e9s avec l&#8217;API 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\":\"Powerful Transactional Email APIs that enable you to send, receive, and track emails, built with developers in mind. Learn more today!\",\"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":"Build Transactional Email Workflows for Abandoned Cart Messages","description":"Learn how to send effective abandoned cart emails using Mailgun APIs to manage and enhance your ecommerce conversions.","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\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/","og_locale":"fr_FR","og_type":"article","og_title":"Build Transactional Email Workflows for Abandoned Cart Messages","og_description":"Learn how to send effective abandoned cart emails using Mailgun APIs to manage and enhance your ecommerce conversions.","og_url":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/","og_site_name":"Transactional Email API Service For Developers | Mailgun","article_modified_time":"2026-04-30T04:28:10+00:00","og_image":[{"width":2466,"height":1532,"url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-25-at-3.37.12-PM.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/","url":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/","name":"Build Transactional Email Workflows for Abandoned Cart Messages","isPartOf":{"@id":"https:\/\/www.mailgun.com\/fr\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/#primaryimage"},"image":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-25-at-3.37.12-PM.png","datePublished":"2025-10-28T09:00:00+00:00","dateModified":"2026-04-30T04:28:10+00:00","description":"Learn how to send effective abandoned cart emails using Mailgun APIs to manage and enhance your ecommerce conversions.","breadcrumb":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/#primaryimage","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-25-at-3.37.12-PM.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/08\/Screenshot-2025-08-25-at-3.37.12-PM.png","width":2466,"height":1532},{"@type":"BreadcrumbList","@id":"https:\/\/www.mailgun.com\/fr\/blog\/dev-life\/creer-des-scenarios-d-emails-transactionnels-pour-les-notifications-de-paniers-abandonnes\/#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":"Cr\u00e9er des sc\u00e9narios d&#8217;emails transactionnels pour les notifications de paniers abandonn\u00e9s avec l&#8217;API 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":"Powerful Transactional Email APIs that enable you to send, receive, and track emails, built with developers in mind. Learn more today!","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\/13386","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":0,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog\/13386\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/media\/11750"}],"wp:attachment":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/media?parent=13386"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog_category?post=13386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}