Localize your emails with ChatGPT and Python

Need to send the same email in different languages? Localized emails using Mail Merge Templates and ChatGPT are more powerful

Localize your emails with ChatGPT and Python

Companies today rely on remote workers or have multiple offices worldwide. Sending emails in English is fine, as it’s the worldwide business language, but wouldn’t it be nice to localize your emails, so your employees will get a translation into their local language? Using ChatGPT and Python, getting localized emails becomes an easy task.

Sure, you can translate the emails yourself if you know the target languages, but what if you’re sending emails to Spanish, French and German recipients? Maybe you can use Google Translate or hire a translator. By using ChatGPT, we just need to run a script and let the magic happen.

We’re going to create localized emails using ChatGPT.

Is your system ready?

If you already have the Nylas Python SDK installed and your Python environment configured, continue with the blog.

Otherwise, I recommend reading the post How to Send Emails with the Nylas Python SDK, where the basic setup is clearly explained.

What are we going to talk about?

What our application will look like

Before moving on, be advised that we’re going to rely heavily on the work we did in the blog post How to Create a Mail Merge Template with Ruby.

Before we jump into the code, let’s see how our application actually works. Although for that, we need an essential step: creating a .csv file containing all the emails and information we will use.

The file will look like this:

AlvaroTejada Galindoxxx@gmail.comSpanish
BlagTejada Galindoxxx@nylas.comEnglish
Alvaro aka “Blag”Tejada Galindoyyy@gmail.comFrench

This is how our application will look:

Localized Emails with ChatGPT

Here, we can fill in the subject, and the body and select the .csv file that we created. 

We will get an error message if we don’t specify all the fields.

You must specify all fields

The exciting part here is how we define the subject and the body.

Localized Emails with ChatGPT example

Here, {Name} and {Last_Name} will be replaced by the values stored on the .csv file. So each recipient will get a personalized or localized email. Remember that the values used between brackets need to match the column names in the .csv file.

Also, the email message will get translated into the target language for each recipient using ChatGPT to turn them into localized emails.

Let’s click Submit and see what happens:

Confirmation message

We have successfully sent emails to all recipients. Let’s check their inbox.

English to Spanish translation:

Email translated into Spanish

English to French translation:

Email translated into French

English doesn’t need to be translated:

Email not translated as it's already in English

As we can see, all recipients received a personalized or localized email, as all the fields were replaced accordingly and it includes a translated version of the message.

Creating a ChatGPT Account

First, we need to have a ChatGTP account and then create our API keys:

Creating ChatGPT account

Once the key has been created, store it safely, as you cannot recover it, so we can take advantage of our .env file and store it there.

Installing the required packages

As we want to create a Flask web application, our best option is to use Flask, one of the most popular Micro Frameworks in the Python world:

$ pip3 install Flask
$ pip3 install Flask-session

Also, we need to install the OpenAI Python package:

$ pip3 install openai

Once they’re both installed, we’re ready to go:

First, we’re going to create a folder called localized_emails, and inside we’re going to create another folder called templates.

Let’s create a file called localized_emails.py in the localized_emails folder and add the following code:

# Import your dependencies
from flask import Flask,render_template,request,flash,redirect,url_for,session
from flask_session.__init__ import Session
import os
import openai
import csv
import re
from nylas import APIClient

# Load your env variables
from dotenv import load_dotenv

# Create the app
app = Flask(__name__)
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"

# Initialize your Nylas API client
nylas = APIClient(

# Initialize your Open API client
openai.api_key = os.environ.get("OPEN_AI")

# This the landing page
@app.route("/", methods=['GET','POST'])
def index():
# We're using a GET, displat landing page
    if request.method == 'GET':
        return render_template('main.html')
# Get parameters from form
        subject = request.form["subject"]
        body = request.form["body"]
        mergefile = request.form["mergefile"]
# Session variables		
        session["subject"] = subject
        session["body"] = body
# Make sure all fields are filled		
        if not subject or not body or not mergefile:
            flash('You must specify all fields')
            return redirect(url_for('index'))
            session["subject"] = None
            session["body"] = None	
# Auxiliary variables
            email = ""
            emails = []
            row_header = {}
            i = 0
            subject_replaced = subject
            body_replaced = body
# Open the CSV file			
            file = open(mergefile)
# Read the CSV contents			
            mergemail_file = csv.reader(file)
# Read and save the headers			
            headers = []
            headers = next(mergemail_file)
            for header in headers:
                row_header[header] = i
                i += 1
# Read all rows of the CSV file				
            for row in mergemail_file:
# Assign parameters to auxiliary variables				
                subject_replaced = subject
                body_replaced = body
# Read all headers				
                for header in headers:
# Search for header and replace them with
# the content on the CSV file					
                    if re.search("{"+f"{header}"+"}", subject):
                        subject_replaced = re.sub("{"+f"{header}"+"}", 
                                           row[row_header[f"{header}"]], subject_replaced)
                    if re.search("{"+f"{header}"+"}", body):
                        body_replaced = re.sub("{"+f"{header}"+"}", 
                                        row[row_header[f"{header}"]], body_replaced)					
#Try to get the Name and Last_Name
                        full_name = row[row_header["Name"]] + row[row_header["Last_Name"]]
                    except Exception as e:
                        full_name = row[row_header["Name"]]
# Translate only email where target language is not English
                if row[row_header["Language"]] != "English":
# Prompt for ChatGPT					
                    prompt = """
                    Translate the following message into language
                    message: text_here
# Replace Language and text_here with proper information					
                    prompt = re.sub("language", row[row_header["Language"]], prompt)
                    prompt = re.sub("text_here", body_replaced, prompt)
# Call ChatGPT
                    response = openai.Completion.create(model="text-davinci-003", 
                                                        prompt=prompt, max_tokens=100, temperature=0)
# Add response to the body of the email
                    body_replaced = body_replaced + "\n\n---" + f'{row[row_header["Language"]]}' + 
                                    " translation follows---\n" + response["choices"][0]["text"]
# Replace carriage returns with break lines
                    body_replaced = re.sub('\n', '<br>', body_replaced)
                    body_replaced = re.sub('\n', '<br>', body_replaced)
# Try to send an email
# Create the draft					
                    draft = nylas.drafts.create()
# Add the subject					
                    draft.subject = subject_replaced
# Add the body
                    draft.body = body_replaced
# Add the recipient and email					
                    draft.to = [{"name":full_name,"email":row[row_header["Email"]]}]
# Send the email					
# It was successful, added to the emails array					
                    email = row[row_header["Email"]]
                except Exception as e:
# There's a problem					
# Call the results page					
    return redirect(url_for('results', emails = emails))	
# Show recipients emails
@app.route("/results", methods=['GET'])
def results():
# Get the list of emails	
    emails = request.args.getlist('emails')
# Call the results page passing emails as parameters	
    return render_template('results.html', emails = emails)
# Run our application  
if __name__ == "__main__":

Inside the templates folder, we need to create 3 different files, let’s start with base.html:

<!DOCTYPE html>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<script src="https://cdn.tailwindcss.com"></script>
	<title>Localized Emails</title>
<div id="container">		
  {% with messages = get_flashed_messages() %}
    {% if messages %}
      {% for message in messages %}
      <div class="flash bg-green-300 border-green-600 border-b p-4 m-4 rounded grid 
                  place-items-center text-red-600 font-bold">
        {{ message }}
      {% endfor %}
    {% endif %}
  {% endwith %}	
  {% block content %}  
  {% endblock %}

Then, main.html:

{% extends 'base.html' %}

{% block content %}
<div class="bg-green-300 border-green-600 border-b p-4 m-4 rounded grid place-items-center">
<p class="text-6xl text-center">Localized Emails</p>
<form method="post">
<label for="subject" class="font-bold">Subject: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
<input type="text" name="subject" value="{% if session.subject != None %} {{session.subject}} {% endif %}" size="50"></input>
<label for="body" class="font-bold">Body:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
<textarea name="body" rows=10 cols=49>{% if session.body != None %} {{session.body}} {% endif %}</textarea>
<label for="mergefile" class="font-bold">Merge File: &nbsp;</label>
<input type="file" name="mergefile">
<button type="submit" class="block bg-blue-500 hover:bg-blue-700 text-white text-lg mx-auto py-2 px-4 rounded-full">Submit</button>
{% endblock %}

And finally results.html:

{% extends 'base.html' %}

{% block content %}
<div class="bg-green-300 border-green-600 border-b p-4 m-4 rounded grid place-items-center">
	<h1 class="text-3xl"> The email was sent to the following addresses</h1>
	{% for email in emails: %}
		<p class="font-semibold">{{ email }}</p>
	{% endfor %}

<div class="bg-green-300 border-green-600 border-b p-4 m-4 rounded grid place-items-center">
<a href="/" class="text-blue-600">Go back</a>
{% endblock %}

Running our Localized Emails with ChatGPT Application

In order to run our application, we just need to type the following on the terminal window:

$ python localized_emails.py
Running our localized emails with ChatGPT

Our application will be running on port 5000 of localhost, so we just need to open our favourite browser and go to the following address:


We have easily created localized emails using ChatGPT.

If you want to learn more about our Email APIs, please go to our documentation Email API Overview.

You can sign up Nylas for free and start building!

Don’t miss the action, join our LiveStream Coding with Nylas:

You May Also Like

How to add Zoom to your event meetings
Nylas_Gartner Cool Vendor
Nylas recognized as a Cool Vendor in the Gartner 2023 Cool Vendors in Composable Customer Engagement Platforms
How to manage your Contacts using Reflex (Pynecone)

Subscribe for our updates

Please enter your email address and receive the latest updates.